Repository navigation
docs(adr): ADR-0070 D2 amended — a type: module sub-package of an installed app may be disabled, not authored into, by an admin (#28285) - #28430
Conversation
…sub-package of an installed app Records the maintainer's ruling of 2026-10-30 (「大包 + 设置里启用模块」, then 「同意」) as a dated amendment note under D2, naming the tie the disable door reads as shipped: a type: module package whose manifest.dependencies directly names an installed type: app package, not system/cloud scoped. Authoring stays refused (isWritablePackage unchanged), the navigation fold drops a disabled package's contributions, and its record-change flows are withheld for in-process writes. The in-process access question is recorded as open. The Status line carries the dated pointer the registry's convention requires. Claude-Session: https://claude.ai/code/session_01FEkQ5nCt4UPJjChW4GyQxQ Co-authored-by: Claude <noreply@anthropic.com>
|
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo Contract reviewServed-tier: Inputs read: card #28285 (body, triage, unblock, claim, dev report ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgmentThe amendment note, sentence by sentence against
ADR-0146 supersession. Its supersede table row for ADR-0070 names D3 (select-or-create a base first) and D5 (retire the stopgaps) for the paired case only, and its pointer on ADR-0070's Status line says "D1, D2, D4 and D6 stand". D2 is not superseded, so an amendment under D2 sits beside ADR-0146. Its D3 pair package (a base's customize package) is a project-scope writable base, never a Status-line form. The repo marks an amendment on the Status line as First consumers, and does the text help them. (a) #28118, the Console half (Packages page Enable/Disable on module rows): the note names Findings.
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:server#2 · os-project-manager · session_0186vfjHHMsRXC9EUT9hTFMo 席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」. This PR is Tier H: that authorisation does not reach it. It stays draft until the maintainer approves.
Generated by Claude Code |
Requested by Leehom · project thread
domain:server#2 · os-project-manager · session_01FEkQ5nCt4UPJjChW4GyQxQ
Fixes #28285
Clause-②: no — governed prose only; no accept set, refusal or served shape moves here. The behaviour the note records shipped in PR #28308 (
7abe151b), which declared its ownyes (widening).Metadata-protocol: none
维护者速读
type: module子包可以被管理员停用(不是写入)。说明按代码实际行为写:停用门读取的归属判据(模块包的manifest.dependencies直接声明一个已安装的type: app包,自身 scope 不是 system/cloud)、写入仍拒绝(isWritablePackage不变)、导航折叠丢弃已停用包的贡献、其记录触发流程在进程内写入时也不派发。docs/adr/0070-package-first-authoring.md的 D2 修订块(一个引用段);Status 行末尾的指针。pnpm check:adr-symbol-anchors,预期全部锚点解析(本次新增 5 个符号锚);再把 D2 修订块与packages/runtime/src/domains/packages.ts里isDisableableAppModule的注释对照。docs/adr/**):你的 approve 或亲手合并。另有一个未决问题不在本 PR 内:应用自己的 hook 在进程内读写已停用模块的对象要不要拒绝(决策函 6538936519),修订块只把它记为未决。What changes
One file,
docs/adr/0070-package-first-authoring.md:> **Amended …**form (the form ADR-0087 and ADR-0005 use), recording the maintainer's ruling of 2026-10-30 verbatim and untranslated (「大包 + 设置里启用模块」, then 「同意」) and what shipped in PR feat(runtime): an admin can disable a type:module package of an installed app; its nav contributions and record-change flows stop (#28117) #28308 (7abe151b):isDisableableAppModulemeasured it on both install paths:manifest.type'module',manifest.dependenciesdirectly naming an installedtype: 'app'package, ownmanifest.scopenotsystem/cloud;isWritablePackageunchanged,writablestill means "may author into" and staysfalsefor a module, edit / publish / revert / delete / overwrite still answer422 WRITABLE_PACKAGE_REQUIRED; the door's verdict is served beside it asdisableable(packages: the served package row carries no "may be disabled" verdict, so the Console cannot offer Disable on a suite module the server now accepts #28318, onmain), computed by the same predicate;404 OBJECT_PACKAGE_DISABLEDon the data plane and the by-name reads, its nav contributions dropped by the fold, its record-change flows withheld for in-process writes, enable restores all three, data kept;ctx.api) is recorded as not decided here, with the maintainer as decision letter6538936519on packages: an admin cannot disable a type:module sub-package of an installed app (422 WRITABLE_PACKAGE_REQUIRED), and a disabled package's nav contributions stay in the app #28117.· **Amended** (date, …) — clause; see the amendment note under D2). Nothing else on the Status line moves; D3–D6 are untouched.ADR-0146 check. Its supersession of ADR-0070 covers D3's prompt and D5's destination for the paired case, and its pointer on ADR-0070's Status line says "D1, D2, D4 and D6 stand". D2 is not the superseded part, so the amendment stands beside ADR-0146 and this PR touches no other record.
Five symbol anchors are new, all resolving (
check:adr-symbol-anchorsbelow):packages/runtime/src/domains/packages.ts#isDisableableAppModule,packages/metadata-protocol/src/package-writability.ts#isWritablePackage,packages/spec/src/api/package-api-assembled.zod.ts#SERVED_ROW_VERDICTS,packages/objectql/src/registry.ts#applyNavContributions,packages/triggers/trigger-record-change/src/record-change-trigger.ts#RecordChangeTrigger.Tests
None: a decision record, no tested behaviour changes, so no ablation. The gates that read
docs/adr/**are the verification.Acceptance notes
node scripts/pm/check-governed-merges.mjs --test docs/adr/0070-package-first-authoring.mdanswers exit 3: "⛔ GOVERNED — a human merge is the review record for this PR (governance: human merge IS the review record for governed surfaces — retire the per-PR ADR approval check, add a report-only post-merge audit #9495 regime) … ⚖️ landing tier: H(人合) — the maintainer's hand, or an authorized APPROVED review (GOVERNED_APPROVERS) and then the owning seat lands it. docs/adr/** ×1". This PR stays draft; no seat readies, queues or arms it.dispatch-gates.mjs --tieron the path: "Model tier — MANDATORY: claude-fable-5-1 … the same order fixes the effort floor at xhigh". This session ran atclaude-fable-5-1, effortxhigh(the session record).skip-changesetrides the create:docs/adr/**publishes nothing (fast track).docs/adr/README.mdis current after the edit (node scripts/adr-index.mjs --check: "OK — docs/adr/README.md is current and every record parsed"), so it is not touched.6538936519), the Console half (Packages page: offer Enable / Disable on a suite's type:module rows once the server allows disabling them #28118), D4–D6.pnpm exec eslint --no-inline-config docs/adr/0070-package-first-authoring.mdexits 0 with "File ignored because no matching configuration was supplied": Markdown is outside the eslint config, and the doc gates below are the style authority for this path.Verification
Gates from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff (21 commands), each run on headc2b0e3adwith its exit code captured before any pipe:node scripts/check-adr-links.mjsnode scripts/check-adr-links.mjs --self-testnode scripts/check-closing-keyword-parity.mjsnode scripts/check-closing-keyword-parity.mjs --self-testnode scripts/check-comment-mask-corpus.mjsnode scripts/ci/plan-test-core-shards.mjs --self-testpnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm check:adr-anchorspnpm check:adr-indexpnpm check:adr-symbol-anchorspnpm check:ci-filter-paritypnpm check:closed-ceremony-textpnpm check:cross-package-test-inputspnpm check:doc-authoringpnpm check:driver-memory-censuspnpm check:gitlink-declaredpnpm check:nul-bytespnpm check:pm-governed-mergespnpm check:pm-prior-rulingspnpm check:refd-timer-probepnpm check:watch-hint-literaldispatch-gates --ran: "21 derived famil(ies) accounted for — 21 run, 0 NOT-MEASURED (a DERIVED zero — all 21 recorded an exit code and none of them is 3)". The first pass recorded exit 3 (PREREQUISITE NOT MET:@objectstack/formulaand@objectstack/lintnot built) oncheck:doc-formula-expressions; afterpnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lintunder the verify lock (VERDICT command-exit 0, 1m36s) the gate ran and exited 0, and the record above carries that run.Readings quoted from the gate logs
node scripts/check-adr-links.mjs→ ✅ check-adr-links: 962 relative link destination(s) under docs/adr/ resolvenode scripts/check-adr-links.mjs --self-test→ ✅ check-adr-links --self-test: discrimination, census, ADR-0046 pin and baseline staleness all verifiednode scripts/check-closing-keyword-parity.mjs→ check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 23186 tracked file(s), all registered).node scripts/check-closing-keyword-parity.mjs --self-test→ ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.node scripts/check-comment-mask-corpus.mjs→ ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 19531 files, 0 disagree, 0 unparseable, 186.4s (comparator self-test: 26 cases pass).node scripts/ci/plan-test-core-shards.mjs --self-test→ ✓ plan-test-core-shards self-test: 23 case(s) across 5 batteries.pnpm --filter @objectstack/lint run check:doc-formula-expressions (rerun after the build)→ ✓ check:doc-formula-expressions (field-level*When, Theos:checkfence type-checks avisibleWhenCEL string asstring— any predicate text passes, including calls to functions that exist nowhere #11407): 15 predicate(s) on a statically determinable field layer judged clean; 12 skipped as undeterminable.pnpm check:adr-anchors→ check-adr-anchors: OK (95 anchored file(s), every governing ADR still referenced; 142 decision number(s), each naming one decision or an allowlisted pair; 62056 citation(s) across 8887 file(s) resolve, 37 of them stem-qualified to one record; 2025 decision-letpnpm check:adr-index→ adr-index --report: OK — docs/adr/README.md is current, every record parsed, self-test 46 assertions green. Report-only: this line never reds the step.pnpm check:adr-symbol-anchors→ ✅ check-adr-symbol-anchors: 2952 anchors across 148 records resolve — 691 symbol (663 declaration, 28 literal), 2214 file-level, 47 cross-repo, 6 exempt, 31 continuation. 0 line anchors survive in the path-anchored, backticked continuation, fenced comment headpnpm check:ci-filter-parity→ OK: all 8 root input(s) oftest/test:repoin turbo.json are covered bycoreorcrosspkg, which thetestjob'sif:reads.pnpm check:closed-ceremony-text→ ✓ check-closed-ceremony-text: 5537 shipped file(s) read; none says the ownership ceremony is closed.pnpm check:cross-package-test-inputs→ OK: 31 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split "test:repo" task); 13 walked root(s) judged, 3 on ACCEPTED_WALK_RADII; 4061 test file(s) import a workspace sibling by bare specifier overpnpm check:doc-authoring→ ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 116712 string(s) read in 1627 parsed source(s) (seen floor 40000 strings / 600 sources), no growth, no burn-down unrecorded.pnpm check:driver-memory-census→ check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states "driver-memory census inundeclared-field-write-driver-split.integration.test.tsis stale — a secondpackages/runtimetest consumer (#6468) is outside #5704's "in this one place" ruling #6664 census: 2 ruled consumers". This gate polices the census, never investment.pnpm check:gitlink-declared→ check-gitlink-declared: OK (23186 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare).pnpm check:nul-bytes→ check-nul-bytes: OK (scanned 23087 text file(s) -- 23087 tracked, 0 untracked-not-ignored; skipped 99 binary; no raw ASCII control bytes).pnpm check:pm-governed-merges→ ✓ check-governed-merges --self-test: 537 assertions (the unified governed predicate + near misses, subject→PR spellings, window parsing, the finding(check-governed-merges): the merge queue's build-to-land skew can put a governed landing BELOW a round's --since boundary, where it is silently absent from the audit list #12633 landing window — the QS-7 regression pin in both directions, the topological close beyond the budget, the unprovpnpm check:pm-prior-rulings→ ✓ check-prior-rulings self-test: 155 cases pass (term derivation with its length floor, stopwords and code-span splitting; the governing-text carrier in both measured shapes plus the absent case that is 23 of 27 on the live board; the backticked-CLAUSE and leapnpm check:refd-timer-probe→ OK check-refd-timer-probe: 19525 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.pnpm check:watch-hint-literal→ ✓ check-watch-hint-literal: 75 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 49, ROOT_FILE_WATCH_HINTS 14, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 9 -- every one an array of quoted literals inside its own statement, all 188 of those literalHuman Minimum
packages/specholds no runtime logic. (packages/specuntouched.)pnpm lintscoped to the file is ignored by config (exit 0, see Acceptance notes).main(5da3a8ce), one pull request.skip-changeset); both declaration lines are filled in above.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code