Repository navigation
feat(plugin-security): under a walled posture, raise the access upgrade report in-app in the organization OS_PLATFORM_OWNER_ORGANIZATION names - #25489
Conversation
…de report in-app in the organization OS_PLATFORM_OWNER_ORGANIZATION names Under group/isolated the boot access upgrade report reached the operator only as one error line. OS_PLATFORM_OWNER_ORGANIZATION (an id or slug, read only under a wall) now names the operators' own organization: the report emits the same notification, same dedupKey, stamped with it and addressed to the OS_PLATFORM_OWNER_EMAIL operators, beside the operator line. A value naming no organization logs one error and raises nothing in-app. A configured operator who is not a verified member of it, and an administrator of it who is not a configured operator, each get a warn. Unset, and under single, nothing changes. The walled and single delivery moves into upgrade-report-delivery.ts so the non-access report (#24447) can call it. Claude-Session: https://claude.ai/code/session_01XHebWJmL3ZgbVpjM6JERNA Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 26 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 12 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 21 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin d0b5426a28c84dca9173b33c708d430f981ec864 && git checkout d0b5426a28c84dca9173b33c708d430f981ec864
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ea33919f56a9879f95a00d45418385ff7dbb974f 07d0ee185bab5558df98e7284846a301d1e31ed7 && git checkout -B drift-repro ea33919f56a9879f95a00d45418385ff7dbb974f && git merge --no-ff 07d0ee185bab5558df98e7284846a301d1e31ed7
node scripts/docs-audit/affected-docs.mjs --json ea33919f56a9879f95a00d45418385ff7dbb974f
|
Contract reviewServed-tier: This review uses the declaration face. It is owed only because the PR body and the changeset say ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
席位核对 · ACCEPT · 2026-10-23T16:24Z
Generated by Claude Code |
Requested by Sales · project thread
Fixes #25413
Clause-②: yes (widening)
Metadata-protocol: none
Claim 6367880115 (
domain:servicesseat 1, #6021). The branch is the harness-pinnedclaude/project-thread-mfvys8. It names no issue, so the claim is the identity record for it. #24447 (claim 6367925751) follows on this branch after this PR merges, because its report calls the helper added here.What changed
Under
groupandisolated, the boot access upgrade report reached the operator only as oneerrorline in the server log (option A, ruling 6353787407). The maintainer chose to configure the owner's organization the way the owner's email is configured.@objectstack/types:PLATFORM_OWNER_ORGANIZATION_ENV(OS_PLATFORM_OWNER_ORGANIZATION) andresolvePlatformOwnerOrganization(), beside theOS_PLATFORM_OWNER_EMAILpair. They use the same trim and blank rule.plugin-security, newupgrade-report-delivery.ts: the delivery of a boot upgrade report, moved out ofaccess-upgrade-report.tsso upgrade-impact comparison after v18: report the non-access classes to the administrator, and retire the zero-consumer package-upgrade.zod.ts #24447 can call it (Wanted 6).single: unchanged and byte-identical. The notification is stamped with the Default Organization and goes to itsadmin_full_accessholders plus the operators. The four "reached no administrator" causes are kept.sys_organizationby id, then by slug. The samesecurity.access_upgradenotification is emitted, with the samededupKey, stamped with that organization and addressed to the configured operators. The operator line stays beside it and says a copy went in-app (Wanted 2).errornaming the value and the fix, then the operator line. Nothing is raised in-app and there is no fallback (Wanted 3). An unreadablesys_organization, a missing messaging service, no configured operator, or a refused emit each get the same shape with their own cause.warn, with a state ofno-account,unverifiedornot-member.warn. An administrator here is anowner/adminmembership grade, or anadmin_full_access/organization_admin/organization_admin_no_bypassgrant scoped to it.finds (sys_memberand grants, by organization) plus the platform-admin standing read the bootstrap already uses.warn, and the copy still goes.access-upgrade-report.ts:reportAccessUpgradehands its finding set to the helper. The comparison, the per-category log lines and the payload are unchanged.AccessUpgradeNotifierandAccessUpgradeReportLoggerstay exported as aliases, sosecurity-plugin.tsis not touched (the [maintainer] refactor(plugin-security): splitsrc/security-plugin.ts(10,746 lines, +2,803 in 30 days) along itsSecurityPluginseams, one move-only slice per PR #25223 split series edits it).auto-org-admin-grant.ts:isAdminRoleis exported. It is the existing owner/admin grade test, reused by the warning instead of copied.content/docs/deployment/environment-variables.mdxbesideOS_PLATFORM_OWNER_EMAIL. It says the organization must hold the operators only, and why.Not touched:
security-plugin.ts,packages/core,packages/spec, service-messaging, the ADR.Tests
upgrade-report-delivery.test.ts(new, 17 cases), each with a CONTROL:sys_organization, no messaging, a refused emit, no operatorsys_membersinglewith the setting set and unsetaccess-upgrade-report.wiring.test.ts: a real ObjectQL + SqlDriver +SecurityPlugin. It coversisolatedandgroupwith the setting naming the operator's dedicated organization (one emit, stamped with it, audience the operator, operator line beside it, and the samededupKeyon the next boot), andisolatedwith an unknown value. The existingsingle/ walled / CONTROL cases pass unchanged.packages/types/src/env.test.ts: spelling, unset and blank, and a trimmed id or slug.Verification
Package suites:
pnpm test: exit 0, 215 files, 4485 passed and 45 skipped.env.test.ts: 58 passed.pnpm typecheckfor plugin-security (tsc, scripts and test-typecheck) and for types: exit 0.Dispatch gates: all 100 commands
dispatch-gates --commandsderived exit 0. Two were re-run after a fix:check-plugin-teardown-shape --self-testexited 3 in a shallow clone. Aftergit fetch --unshallowit exits 0.check:where-matcherflagged the new test double. The double now refuses a combinator, and the gate exits 0.check-governed-merges --branch: not governed, 1,100 changed lines.Ablations (committed source, mutated with
scripts/ablation-replace.mjs, restored to HEAD,git diff HEADempty):R1:
OS_LOG_LEVEL=info pnpm dev -- --freshon the showcase logs[security] access upgrade report: every activation ledger row … matches the registry at this boot {"absent":[]}, with no ERROR line.R4: production
os serveof the showcase on a persistent SQLite file, underisolatedandgroup. Rig details:OS_PLATFORM_OWNER_EMAIL=op@r4.exampleandOS_AUTH_MEMBERSHIP_POLICY=invite-onlysys_user,ownerof a dedicated organizationr4-platform-ops, a tenant organization beside it, and the customer's switch-off ofshowcase_auditor(com.example.showcase,active=0)showcase_audit_reader, with theauditorposition binding it, reverted afterwardssys_notificationr4-platform-opsERROR, then the operator line with "A copy is raised in-app …" andorganizationId: org_r4_platform. Onesys_notificationrow (organization_idorg_r4_platform, dedup keysecurity.access_upgrade:a9b3…), one inbox delivery and onesys_inbox_messagerow forusr_r4_operatorin that organization. No row in any other organization, no refused write, no "reached no administrator".[messaging] emit: dedupKey … already emitted; skipping, still one rowr4-platform-opz(unknown)ERROR … "r4-platform-opz" names no organization by id or by slug … Fix: …, then the unset-form operator lineadminmember added to the operator's organizationWARN … 1 administrator(s) … are not configured operators …WARN … 1 configured operator(s) are not verified members … state not-memberThe only other ERROR line on every rig boot is
[auth] no_sign_in_account_at_boot. The rig caused it by insertingsys_userdirectly, and it is present on the CONTROL boot too. The WARN lines match the CONTROL boot's.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01XHebWJmL3ZgbVpjM6JERNA