Context
Split from #138 ("Consolidate trusted workspace context and authorized shard routing"), which is being closed now that its concrete 0.5.0-relevant scope — the downstream shard-routing bugs it was blocking (#253, #204, both fixed via #284; #242, directionally decided) — is done or in flight. This issue tracks the remaining scope from #139's own wrap-up comment that #138 stayed open to hold, which is real follow-up work but was explicitly judged premature ahead of multi-user auth:
What remains — rewriting every service function's signature from (caller, ...) to (context, ...) (~30 functions across documents/collections/records/holds/search); real allowedSpaceIds enforcement; Awareness actor-spoofing prevention; audit-attribution rework for direct Yjs writes — is real but premature: Phase 0 has exactly one principal, so there's nothing to enforce against yet. Becomes meaningful once multi-user auth (Phase 1) exists.
Nothing has changed since that reasoning was written (2026-09-01) — Phase 0 still has exactly one real caller, so none of the three items below can actually reject or misattribute anything yet. This issue exists so the scope isn't lost, not because it's actionable today.
Update (2026-09-13): the signature-rewrite item originally listed here ((caller, ...) → (context: RequestContext, ...)) has been split out into #306, since — unlike the three items remaining below — it's mechanical plumbing that doesn't need a second principal to be meaningful, and it also gives #303's workspace-store.ts globalThis-registry fix a natural home. #306 is P0/Ready in 0.5.0. This issue keeps only the genuinely Phase-1-gated items.
Scope
- Implement real
allowedSpaceIds enforcement in the service layer, using the field RequestContext already carries but doesn't check against.
- Prevent Awareness actor-spoofing: a Yjs Awareness client can currently set an arbitrary actor identity in its local state with nothing validating it matches the authenticated caller.
- Rework audit-attribution for direct Yjs writes so it resolves to a registered connection principal instead of unconditionally
CURRENT_USER (src/lib/server/audit-observer.ts), a Phase-0-only simplification that stops being correct once more than one real user connects.
Non-goals (for now)
Implementing any of the above before Phase 1 (multi-user auth) lands — there is no second principal to scope, spoof-check, or attribute against yet, so doing this work early would be unverifiable and untestable beyond "doesn't break the one existing caller."
Done when: Phase 1's multi-user auth work is underway or landed, at which point each of the three items above either gets implemented as part of that work or is split into its own issue with real acceptance criteria against an actual second principal.
Context
Split from #138 ("Consolidate trusted workspace context and authorized shard routing"), which is being closed now that its concrete 0.5.0-relevant scope — the downstream shard-routing bugs it was blocking (#253, #204, both fixed via #284; #242, directionally decided) — is done or in flight. This issue tracks the remaining scope from #139's own wrap-up comment that #138 stayed open to hold, which is real follow-up work but was explicitly judged premature ahead of multi-user auth:
Nothing has changed since that reasoning was written (2026-09-01) — Phase 0 still has exactly one real caller, so none of the three items below can actually reject or misattribute anything yet. This issue exists so the scope isn't lost, not because it's actionable today.
Update (2026-09-13): the signature-rewrite item originally listed here (
(caller, ...)→(context: RequestContext, ...)) has been split out into #306, since — unlike the three items remaining below — it's mechanical plumbing that doesn't need a second principal to be meaningful, and it also gives #303'sworkspace-store.tsglobalThis-registry fix a natural home. #306 is P0/Ready in 0.5.0. This issue keeps only the genuinely Phase-1-gated items.Scope
allowedSpaceIdsenforcement in the service layer, using the fieldRequestContextalready carries but doesn't check against.CURRENT_USER(src/lib/server/audit-observer.ts), a Phase-0-only simplification that stops being correct once more than one real user connects.Non-goals (for now)
Implementing any of the above before Phase 1 (multi-user auth) lands — there is no second principal to scope, spoof-check, or attribute against yet, so doing this work early would be unverifiable and untestable beyond "doesn't break the one existing caller."
Done when: Phase 1's multi-user auth work is underway or landed, at which point each of the three items above either gets implemented as part of that work or is split into its own issue with real acceptance criteria against an actual second principal.