fix(listing): synthetic table.yaml/form.yaml verbs reflect actual authority

The synthetic spec entries injected into rollup virtual surfaces
(/<project>/{ssr,mdl,rsk}/) had Verbs hardcoded to "r" — so even
an elevated root admin saw the spec files as read-only in the
YAML editor's verbs check (cap.has(node, 'a') returned false →
saveBtn disabled + the red read-only banner).

The hardcode was a Part 2 oversight; every other synthetic listing
entry already computes verbs via EffectiveVerbsFromChainP against
the entry's path. Now table.yaml and form.yaml do the same — elevated
admins get "rwcda" and can PUT a custom spec to override the embedded
default at the rollup view; everyone else still gets "r" via the
project-level project_team:r grant cascading through.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-21 13:23:12 -05:00
parent a6cb847f2f
commit cc7f34e922
2 changed files with 20 additions and 5 deletions

View file

@ -291,11 +291,26 @@ func ListDirectory(ctx context.Context, decider policy.Decider, fsRoot, dirPath,
// Row rollups carry synthetic spec entries so the tables tool
// can walkServer them. Folder-nav virtuals don't need spec
// files — they're just party listings rendered by browse.
// Verbs reflect actual cascade authority at each synthetic
// spec's URL so elevated admins see them as writable (they
// CAN materialise an override .zddc / spec by PUTting to
// the virtual path). Non-admins fall through to the default
// 'r' that the embedded baseline grants on the rollup view.
if zddc.IsRowSlot(vv.Slot) {
result = append(result,
listing.FileInfo{Name: "table.yaml", URL: baseURL + "table.yaml", IsDir: false, Virtual: true, Verbs: zddc.VerbR.String()},
listing.FileInfo{Name: "form.yaml", URL: baseURL + "form.yaml", IsDir: false, Virtual: true, Verbs: zddc.VerbR.String()},
)
for _, spec := range []string{"table.yaml", "form.yaml"} {
specURL := baseURL + spec
verbs := policy.EffectiveVerbsFromChainP(ctx, decider, parentChain, principal, specURL)
if !verbs.Has(zddc.VerbR) {
continue
}
result = append(result, listing.FileInfo{
Name: spec,
URL: specURL,
IsDir: false,
Virtual: true,
Verbs: verbs.String(),
})
}
}
}

View file

@ -1534,7 +1534,7 @@ body.is-elevated::after {
</svg>
<div class="header-title-group">
<span class="app-header__title" id="table-title">ZDDC Table</span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.22-beta · 2026-05-21 16:29:59 · 90a3102</span></span>
<span class="build-timestamp"><span style="color:red;font-weight:bold">v0.0.22-dev · 2026-05-21 18:21:55 · a6cb847-dirty</span></span>
</div>
</div>
<div class="header-right">