feat(audit): record a service/non-user principal on sys_audit_log.actor (ADR-0014 D2, cloud#340)#2101
Merged
Merged
Conversation
…or (ADR-0014 D2, cloud#340) A non-user-authenticated write (e.g. a service token) left `sys_audit_log.user_id` = null and was therefore UNATTRIBUTABLE — exactly how the prod env-delete of `os-790m7q` went unaccountable (a service-token call with no user/IP). `user_id` is a strict `sys_user` lookup, so a service principal can't be stuffed there. This opens the mechanism (the host wires the value — see cloud#340 cloud half): - `spec` ExecutionContext: add an optional `actor` field — a stable principal label for attribution when there's no `userId` (e.g. `svc:<name>`). Additive, backward-compatible; public API surface unchanged. - `plugin-audit` sys_audit_log: add a first-class `actor` text field (the principal label), independent of the `user_id` lookup. `user_id` stays user-only. - audit writer: record `actor = userId ?? session.actor ?? null`. Conditionally stamped (same pattern as organization_id) so audit tables that predate the column keep working. No behavior change until a host sets `ExecutionContext.actor` (cloud control plane will, in service mode). Tests: real user → actor=user id; service token (no userId) → actor='svc:cloud-control', user_id stays null; neither → null. spec 6599/6599 + api-surface ✓; plugin-audit 21/21. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 90 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
added a commit
that referenced
this pull request
Jun 29, 2026
chore(chatbot): upgrade to Vercel AI SDK v7 / @ai-sdk/react v4 (#2101) objectui@8d351f100c149316b41528950fdc423a41f0f7ae
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A non-user-authenticated write — e.g. an
OS_CLOUD_API_KEYservice-token call — leftsys_audit_log.user_idnull and was therefore unattributable. That's exactly how the prod env-delete ofos-790m7qwent unaccountable (service-token, no user/IP/UA).user_idis a strictsys_userlookup, so a service principal can't be recorded there at all.What — open the mechanism (the host wires the value)
specExecutionContext (execution-context.zod.ts): new optionalactorfield — a stable principal label for attribution when there's nouserId(e.g.svc:<name>). Additive / backward-compatible; public API surface unchanged (the gate tracks export names, not zod field internals).plugin-auditsys_audit_log: new first-classactortext field, independent of theuser_idlookup.user_idstays user-only.actor = userId ?? session.actor ?? null. Conditionally stamped (same pattern asorganization_id) so audit tables that predate the column keep inserting cleanly; the column auto-adds on the next schema sync.This is the open half (ADR-0012 style): the framework defines + records the contract; the host sets
ExecutionContext.actor. The cloud control plane will setsvc:<name>in service-mode auth (cloud#340 cloud half) — no behavior change here until it does.Tests
actor = user id,user_id = user idactor = 'svc:cloud-control',user_idstays null (the os-790m7q class, now attributable)actornull@objectstack/spec6599/6599 +check:api-surface✓;@objectstack/plugin-audit21/21; spec build clean.Pairs with cloud#340 (cloud sets the service-mode actor + names the token). Relates to cloud ADR-0014 D2.
🤖 Generated with Claude Code