feat(platform-objects): secure-by-default posture for sensitive system objects (ADR-0066 ④)#2691
Merged
Merged
Conversation
…m objects (ADR-0066 ④)
The platform's raw secret/credential stores no longer ride the wildcard `'*'`
permission grant. `sys_secret`, `sys_jwks`, `sys_verification`,
`sys_oauth_access_token`, `sys_oauth_refresh_token`, and `sys_device_code`
declare `access: { default: 'private' }` — an ordinary member's generic
data-layer access gets 403; platform admins retain access via the
posture-gated viewAllRecords/modifyAllRecords superuser bypass.
Every runtime consumer is unaffected (verified per reader): better-auth reads
via its adapter (system context), `engine.resolveSecret` reads at driver
level, SettingsService / the datasource secret-binder read principal-less
(middleware falls open for internal calls), API-key auth reads isSystem.
- `sys_scim_provider` gains `requiredPermissions: ['manage_platform_settings']`
(D3 capability gate), mirroring its sibling `sys_sso_provider`.
- Setup nav `nav_jwks` is capability-gated like `nav_api_keys` so non-admins
don't see a menu entry that can only 403.
- Member self-service objects (sys_session, sys_api_key,
sys_oauth_application, sys_two_factor) deliberately keep the public
posture — the Account app reads them as the member; row scoping is their
guard. A test asserts this exclusion too.
- Pinned against regression: platform-objects.test.ts posture suite + the
ADR-0056 D10 conformance-matrix row `secure-by-default-posture`.
Tests: platform-objects 71, plugin-auth 230, dogfood conformance +
anonymous-deny + two-doors e2e, service-settings 129, service-datasource 93 —
all green; full turbo build green.
Refs #2561
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0187GeNqezxV6g5jiLiggfbt
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…ADR-0066 ④) The Advanced table listed Verifications and Device Codes, but those nav entries were deliberately removed (sensitive ephemeral secrets — not browsable; see setup-nav.contributions.ts). Also document that nav_jwks is capability-gated and sys_jwks is private-posture. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0187GeNqezxV6g5jiLiggfbt
os-zhuang
marked this pull request as ready for review
July 8, 2026 16:03
18 tasks
baozhoutao
added a commit
that referenced
this pull request
Jul 19, 2026
fix(app-shell,plugin-detail): record History tab renders display values, not raw audit payloads (#2691) objectui@e164196801bd38e1396798877a69e0a09e80d8d3
baozhoutao
added a commit
that referenced
this pull request
Jul 19, 2026
…e164196801bd (#3294) * ci(release): bump downstream-smoke HOTCRM_REF to v2.1.0 (agent visibility removal) hotcrm v2.0.0 still authors the agent `visibility` field that #3216 removed from the spec (ADR-0056 D8), so the pre-publish downstream smoke has been red and the release train is stalled. Point the gate at hotcrm v2.1.0, which drops the field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: bump objectui to e164196801bd fix(app-shell,plugin-detail): record History tab renders display values, not raw audit payloads (#2691) objectui@e164196801bd38e1396798877a69e0a09e80d8d3 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
os-zhuang
added a commit
that referenced
this pull request
Jul 22, 2026
The v16 sweep (#3358 §4 "Record History tab") couldn't exercise the tab because no showcase object opted into it: the console gates the History tab on object-level `enable.trackHistory` (RecordDetailView) — audit *capture* is always on, but the *tab* is opt-in — and the showcase only set `trackHistory` at the FIELD level (industry/status), which just selects which diffs are summarized. So the tab never rendered anywhere and #2691/#3293 (display-value diffs, computed-field exclusion) were undemonstrated. Set `enable: { trackHistory: true }` on Account (which already declares field-level `trackHistory` on `industry`/`status` for clean diffs). Verified in the running app: the Account detail now shows a **历史 / History** tab; after editing `industry`, it renders "Dev Admin · UPDATE · 行业: Retail → Technology" — field label + select **display values** (not raw stored codes/ids), no phantom value→null rows. `os validate` + `tsc --noEmit` pass. Follow-up to #3364 / #3393, from the #3358 sweep §4. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.
What & why
Lands the system-object slice of ADR-0066 ④ (secure-by-default rollout) from the authorization gap map (umbrella #2561). The D2
access: { default: 'private' }primitive has been enforced since #2690's predecessors — but no production object used it: the platform's raw secret/credential stores were still covered bymember_default's wildcard'*': allowRead. This PR flips the clearly-sensitive, flip-safe ones.Change
6 objects →
access: { default: 'private' }sys_secretsys_jwkssys_verificationsys_oauth_access_tokensys_oauth_refresh_tokensys_device_codeAn ordinary member's generic data-layer access now 403s; platform admins retain access via the posture-gated
viewAllRecords/modifyAllRecordssuperuser bypass.Flip-safety — every runtime consumer verified
isSystem: true→ middleware short-circuits; auth flows unaffected.engine.resolveSecretreadssys_secretat driver level (below the middleware).core/security/api-key.ts) reads withisSystem: true.Deliberately excluded (member self-service)
sys_session,sys_api_key,sys_oauth_application,sys_two_factorkeep the public posture: the Account app ("My Sessions" / "My API Keys" / "My Apps" / 2FA "My Enrollment") reads them through the generic data layer as the member — flipping them would break self-service. Row scoping (owner/tenant RLS +_selfcarve-outs) remains their guard. A test asserts the exclusion so it's a documented decision, not an oversight.Also
sys_scim_provider(SCIM bearer-token config) gainsrequiredPermissions: ['manage_platform_settings']— mirrors its siblingsys_sso_provider's D3 gate.nav_jwksis capability-gated likenav_api_keys(UX: non-admins no longer see a menu entry that can only 403).Regression pinning
platform-objects.test.ts— "secure-by-default posture" suite asserts each flip and the self-service exclusions.secure-by-default-posture(dropping the flag from a secret store fails CI, not review).content/docs/permissions/authorization.mdxupdated: system-object slice landed; still open = Studio posture surfacing (objectui) and the explicit-publicreference-data convention (no such objects ship in framework today).Tests / verification
platform-objects: 71 passed (incl. new posture suite)plugin-auth: 230 passed (auth flows unaffected by the flips)showcase-anonymous-deny+two-doors-permissione2e (real kernel boot + login) 8 passedservice-settings129 +service-datasource93 passed (thesys_secretconsumers)turbo buildgreenRefs #2561
🤖 Generated with Claude Code
https://claude.ai/code/session_0187GeNqezxV6g5jiLiggfbt
Generated by Claude Code