20260701000001_cogmap_write_tightening.sql),kb_access_grants write row (orVerified live 2026-07-06: a principal with read on the team map 019f2391(via
membership) but no write grant was deniedfold_relationship("cannot modify this
resource") and could not self-grant (cogmap_grant→granted:false). The only
write-holder is the steward's granted M2M principal.
DbBackend call them, never inlining the SQL.| Predicate | Question | Definition |
|---|---|---|
cogmap_authorable_by_profile(profile, cogmap) | May profile author into this map? | profile_explicit_grant(profile, 'write', 'kb_cogmaps', cogmap) — explicit write grant only (cogmaps have no owner) |
context_authorable_by_profile(profile, context) | May profile author into this context? | personal-owner, reachable-member-of-owning-team, or an explicit can_write grant |
can_modify_resource(profile, resource) | May profile modify this existing resource? | resource's home owner/originator, an explicit per-resource (kb_access_grants, can_write) grant, or write on the resource's home container (cogmap_authorable_by_profile / context_authorable_by_profile) — the container-write cascade |
anchor_readable_by_profile(profile, 'kb_cogmaps', cogmap) | May profile read this map? | membership-broad read visibility |
can_modify_resource consults the resource's own ownership/grants and its homecogmap_authorable_by_profile) or a context writer (context_authorable_by_profile)fold/facet/assert-from/update nodes another principalcontext_authorable_by_profile's team-owner arm (a member of the owning team mayinternal/superpowers/specs/2026-07-06-container-write-cascade-and-authz-hardening-design.md.)| Operation | Gate | Enforced in |
|---|---|---|
create_resource into a cogmap | cogmap_authorable_by_profile (write grant) | DbBackend::create_resource (F1) + the surfaces (MCP create_resource tool + HTTP ingest) as fast-fail pre-checks, via the shared cogmap_service::authorable_by_profile seam |
assert_relationship | can_modify_resource(source) — incl. container cascade | DbBackend::check_can_modify_next |
fold_relationship / retype / reweight | can_modify_resource(source) — incl. container cascade | DbBackend::check_can_modify_next |
facet_set | can_modify_resource(resource) — incl. container cascade | DbBackend::check_can_modify_next |
update_resource / delete_resource | can_modify_resource(resource) — incl. container cascade | DbBackend::check_can_modify_next |
advance_steward_watermark | cogmap_authorable_by_profile (write grant) | DbBackend |
materialize / materialize_delta | cogmap_authorable_by_profile (write grant) | DbBackend |
invocation_open (self-attributed, parent = None) | cogmap_authorable_by_profile — WRITE (F2) | DbBackend::check_cogmap_authorable |
invocation_open (delegated, parent = Some) | anchor_readable_by_profile — READ; substrate enforces parent→originating lineage | DbBackend::check_can_read_cogmap |
DbBackendcan_modify_resource, which now cascades from container write); create-into-cogmapDbBackend (F1) — the surfaces keep a matching pre-check for fast-failcogmap_service::authorable_by_profileresource create → POST /api/ingest), and API all enforce the same rule. DbBackendclient_credentials); it authors 019f2391 because it holds an explicit writeprofile_id, and every gate evaluates that id.--team <ref>[:role]watcher, so it clears thesystem_access gate. That is the point of the design: a machine's reach is ordinary teamsDbBackend::create_resource now checks cogmap_authorable_by_profile on a Cogmap homecheck_cogmap_authorable), before any write — so the shared write path denies even ais_active failure mode this directoryinvocation_open is write-gated for self-attributed opens ✅parent = None) now requires cogmap_authorable_by_profileparent = Some) keeps thetemper-mcp/.../resources.rs, temper-api/.../ingest.rs,cogmap_service.rs) now name cogmap_authorable_by_profile = an explicit write grant