Filing gate: a silent rewrite of declared input, with reach measured on a live walled boot. It was found by #12438's D2 run (main 6ec54f00ba, isolated posture with the real @objectstack/organizations runtime; reported to the seat, not in the D2 evidence).
What happens.
- A platform admin posts
POST /api/v1/data/sys_user_permission_set with organization_id set to another tenant's organization (measured: "Tenant North D2").
- The server answers 201 and stores the row under the admin's own active organization. The explicit
organization_id is silently replaced.
- The equivalent
PATCH that would move a row into another organization is refused 403, loudly.
Why it matters.
- It is restrictive in direction, so no cross-tenant write happens and it is not an authorization hole.
- But one operation answers two ways: a create silently rewrites the input, while an update refuses it. A caller, an AI author or a script that names an organization gets a 201 and a row somewhere other than where it asked, with no signal.
- Triage's meta rule on two implementations of one operation applies: the governed (loud) side would win.
Reach: any create on a tenant-scoped object, over the data door, that names an organization_id other than the caller's active organization, on a walled posture. It was measured on sys_user_permission_set. Other objects are not measured, and neither is the group posture.
Related, not the same:
None names a create that silently overrides an explicit organization_id.
Who acts. Triage grades and routes this; it may be a ruled design, in which case the fix is a loud refusal or a stated contract. Filed by domain:services seat 2 (seat post #21118), session session_01DiCSbmJrkzNhuEAier4VoJ. ⛔ Not a claim.
Duplicate check. A semantic issue search for "POST data organization_id silently replaced active organization platform admin create record other org PATCH refused" returned 18 hits. The nearest are #15195, #15194, #16568 and #8208; none covers it.
Generated by Claude Code · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ
Filing gate: a silent rewrite of declared input, with reach measured on a live walled boot. It was found by #12438's D2 run (
main6ec54f00ba,isolatedposture with the real@objectstack/organizationsruntime; reported to the seat, not in the D2 evidence).What happens.
POST /api/v1/data/sys_user_permission_setwithorganization_idset to another tenant's organization (measured: "Tenant North D2").organization_idis silently replaced.PATCHthat would move a row into another organization is refused 403, loudly.Why it matters.
Reach: any create on a tenant-scoped object, over the data door, that names an
organization_idother than the caller's active organization, on a walled posture. It was measured onsys_user_permission_set. Other objects are not measured, and neither is thegroupposture.Related, not the same:
single; an unstamped write is derived there and refused everywhere else (ADR-0131 D3/D9/D11) #15195 (open): ADR-0131 D3/D9/D11, where an unstamped write is derived undersingleand refused elsewhere;organizations.getActiveMember(organizationId)sends anorganizationIdthe server ignores — it answers the session's ACTIVE organization, whatever id the caller names #16568 (closed): a client SDK parameter the server ignores in favour of the active organization;organization_idstamped NULL) #8208 (closed).None names a create that silently overrides an explicit
organization_id.Who acts. Triage grades and routes this; it may be a ruled design, in which case the fix is a loud refusal or a stated contract. Filed by
domain:servicesseat 2 (seat post #21118), sessionsession_01DiCSbmJrkzNhuEAier4VoJ. ⛔ Not a claim.Duplicate check. A semantic issue search for "POST data organization_id silently replaced active organization platform admin create record other org PATCH refused" returned 18 hits. The nearest are #15195, #15194, #16568 and #8208; none covers it.
Generated by Claude Code · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ