Skip to content

[finding] sys_position.permissions is a declared "JSON-serialized array of permission strings" column and nothing writes or reads it #9885

Description

@os-warren

Measured by the recurring no-verdict enumeration patrol established in the #9054 ruling (2026-08-16): "run the no-verdict enumeration periodically … and report 'keys with zero readers' as findings — enumeration without verdicts, never a red gate, never a ledger row." Filed unassigned by the triage seat (session session_01JEhkB6ShK2HHDzozy7Qwgz); observation-class. ⛔ No verdict attached and none should be added — this card records a measurement, not a liveness claim.

The key

packages/plugins/plugin-security/src/objects/sys-position.object.ts:196 declares on sys_position:

  • permissions — Field.textarea, "JSON-serialized array of permission strings", group Configuration.

The measurement (at origin/main 07bfd31cb)

A whole-tree word search (git grep -lw permissions over packages/, apps/, examples/, all .ts/.tsx, tests included) is inconclusive for this token by itself — 441 files, which is exactly the generic-token collision #8894's measurement documented (ExecutionContext.permissions, object_permissions, route paths, …). So the second pass is object-scoped, per that measurement's own lesson: all 97 files naming sys_position in code were read for a permissions row-column access. Result:

  • No producer. The only row writers are bootstrap-builtin-positions.ts (writes label, description, managed_by, active, is_default) and bootstrap-declared-positions.ts (writes label, description, active, is_default). Neither writes permissions.
  • No reader. Position→grant resolution never consults it: packages/core/src/security/resolve-authz-context.ts resolves position-bound sets through sys_position_permission_set rows (:474-476) and sys_position.name (see packages/spec/liveness/position.json: "sys_position.name keys position-bound permission-set resolution"); delegated-admin-gate.ts reads name/delegatable/is_default/business_unit_id; sharing-rule-service.ts reads active. Every other permissions occurrence in those 97 files is ExecutionContext.permissions (caller-context set names), a sys_permission_set column (object_permissions etc.), or route/prose text.
  • In-file references exist but originate nothing: the clone_position action copies it ({ field: 'permissions', defaultFromRow: true }, sys-position.object.ts:118, comment "permissions JSON is copied wholesale") — a copy of a value no code ever writes or evaluates.

Why this is the ADR-0049 class

The declared surface reads as a capability catalogue: a Permissions textarea on Position tells an admin — and an AI agent authoring against this model — that granting permission strings directly on a position is a thing the platform does. It is not: grants flow only through permission-set bindings. Same shape as sys_permission_set.active pre-#8613 and the #9046 D5 pair, on the same ungoverned row-column half of the ADR-0049 surface. Notably, #8894's read-oracle scored this key green for the same reason it stayed green on sys_permission_set.active — the token is generic — which is precisely the blind spot the no-verdict patrol exists to cover by hand.

Corroboration that this is not a search artifact

Same-object positive controls under the identical search shapes: sys_position.active resolves to real readers (sharing-rule-service.ts:65,92; row-active.ts per #8710), delegatable and is_default to delegated-admin-gate.ts (:758 for is_default), name to permission-evaluator.ts:380. Cross-object controls: valid_until → delegated-admin-gate.ts:476; granted_by → sharing-plugin.ts:873. Only permissions comes back empty on both sides.

⚠️ Scope of the negative claim: this repo only, per the evidenceScope discipline (packages/spec/liveness/README.md). objectui was not searched; a designer preview rendering the column would count as a consumer under the 2026-08-10 ruling — though not as enforcement, and not as a producer.

Patrol coverage note for the record: this round enumerated the full #8894 surface — 88 candidate keys across the 10 plugin-security/plugin-sharing platform objects; 85 live, 4 already covered by #9046 (the D5 pair ×2 tables), 1 already adjudicated (#8535, sys_capability.active), and this key is the only unfiled zero/zero. Dedup checked (key-name, symptom, patrol phrasing): only #8710 surfaces, which concerns sys_position.active — a different key.

Refs: #9054 (the ruling that runs this patrol) · #8894 (the measurement + oracle) · #9046 (the D5 pair, same patrol) · #8613 · #8535 · ADR-0049 · ADR-0090.

Activity

  1. added theissue type on Aug 19, 2026
  2. os-warren commented on Aug 19, 2026

    @os-warren
    CollaboratorAuthor

    Triage first-touch grading: graded off finding → needs-user-decision (enforce-or-remove channel — removing an authorable, published column is on the human floor, same as its class siblings; the patrol's own no-verdict rule binds the measurement, and this grading is the downstream step it feeds).

    Recommendation: A — REMOVE sys_position.permissions (and the clone_position copy entry) via the standard ADR-0049/ADR-0087 retirement flow, docs/table riders included; objectui designer-preview check (the stated evidenceScope gap) folded into the retirement PR's checklist. B — enforce: design and implement direct position-level permission grants (a real security feature — only if the maintainer wants that capability). C — leave declared-and-inert.

    Confidence gap: objectui was not searched (evidenceScope: this repo only) — if the console's position designer renders or persists this column, removal needs the consumer-side rider; and this analysis cannot see customer deployments that may have hand-filled the column as documentation-of-intent.


    Generated by Claude Code

  3. removed their assignment
    on Aug 20, 2026
  4. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    Maintainer ruling recorded (2026-08-20, live decision-inbox session with the triage seat, session session_01PjAP6vbcsg2yMtvySPv1Qo)

    Ruled: remove sys_position.permissions under ADR-0049 enforce-or-remove. Provenance: maintainer accepted the batch, verbatim: 「其他接受你的建议。」Zero producers, zero readers (object-scoped 97-file sweep with same-object positive controls); the declared surface reads as a capability catalogue the platform does not have, which is exactly the AI-misleading shape the patrol exists to catch. Scope includes the clone_position copy line ({ field: 'permissions', defaultFromRow: true }) — a copy of a value nothing writes.

    Route per the spec-property-retirement playbook (ledger verdict confirmation, ADR-0087 conversion, baselines/forms/docs/pin tests as applicable to a platform-object row column). Clause-②: yes (declared-surface removal) — contract-review tier. objectui was not searched (evidenceScope) — the dev's first step is the consumer check there before deleting.

    State transition in the same stroke: needs-user-decision → pm:queue.


    Generated by Claude Code

  5. self-assigned this
    on Aug 20, 2026
  6. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    Claim: PM loop round 1
    Session: session_01DdCnBGcHeufjrq7drTD3wt
    Branch: claude/issue-9885-retire-sys-position-permissions
    Worktree: objectstack-issue-9885
    Domain: domain:services — ⚠️ not this seat's lane; maintainer direct-dispatch, see below
    Container & model: M, mode:subagent, model: claude-fable-5 (CONTRACT_REVIEW_TIER, read live from scripts/pm/dispatch-gates.mjs:1943)
    File surface: packages/plugins/plugin-security/src/objects/sys-position.object.ts + the retirement playbook's required riders (ledger, ADR-0087 conversion, generated baselines, forms, docs, pin tests) + changeset (stop on breach; explain in the report)
    Clause-②: yes — declared-surface removal
    Serial constraints cleared: No open PR touches packages/plugins/plugin-security — repo-wide open PRs at claim time: #10150, #10147, #10157. Sibling in-flight from this seat: #9930 (plugin-webhooks), #10091 (service-storage), #9877/#10138 (scripts/**) — all disjoint. ⚠️ #9930 is in the same batch and also runs a retirement-shaped flow; different package, different key, no file overlap.

    ⛔ Cross-lane authorisation — maintainer direct-dispatch channel

    domain:services card, dispatched by the domain:devx seat. Maintainer's instruction to this session, verbatim:

    #9930 · #9885 也插队

    Per-card. domain:* untouched. It comes here for the same reason as #10091 and #9930: Clause-② requires the contract-review tier, and that lane has no fable. This session does, so it runs at the ruled tier — no deviation, no exemption.

    裁决 (maintainer, 2026-08-20, 「其他接受你的建议。」 — recorded in 5353923232)

    REMOVE sys_position.permissions under ADR-0049 enforce-or-remove. Scope includes the clone_position copy entry ({ field: 'permissions', defaultFromRow: true }, sys-position.object.ts:118) — a copy of a value nothing writes. Route per the spec-property-retirement playbook: ledger verdict confirmation, ADR-0087 conversion, and the baselines / forms / docs / pin tests that apply to a platform-object row column.

    ⛔ Option B (implement position-level direct grants) is ruled out. ⛔ Option C (leave declared-and-inert) is ruled out.

    ⭐ Your first step is the objectui consumer check — and I have removed the excuse for skipping it

    The ruling says: "objectui was not searched (evidenceScope) — the dev's first step is the consumer check there before deleting." This is the card's one real gap: a console position designer that renders or persists this column is a consumer under the 2026-08-10 ruling (though not enforcement, and not a producer), and it would need a consumer-side rider before deletion.

    ⚠️ You will find that the GitHub API 403s on objectstack-ai/objectui. That is NOT "objectui is unreachable" — I measured both channels:

    GET https://api.github.com/repos/objectstack-ai/objectui   -> 403   (API: repo not attached to this session)
    git clone --depth 1 https://github.com/objectstack-ai/objectui  -> WORKS (public repo, anonymous git read via the proxy)
    

    ⇒ Clone it and grep it. ⛔ Do not report the consumer check as "could not verify" on the strength of the API refusal — an absence measured with the wrong instrument is not an absence, and this exact conflation has now cost this seat three separate wrong conclusions today.

    GIT_LFS_SKIP_SMUDGE=1 git clone --depth 1 https://github.com/objectstack-ai/objectui /workspace/objectstack-ai/objectui
    

    (generous timeout — a shallow pack through the proxy can take several minutes and git index-pack looks stalled while unpacking; ⛔ do not interrupt or re-run it. If the path already exists, check git -C … rev-parse HEAD before touching it — a concurrent clone may be live.)

    Then search for a sys_position + permissions consumer, with same-object positive controls so a zero-hit is a real absence rather than a broken search — the card's own method, and the reason its in-repo claim is credible. ⛔ This session cannot push to objectui; if a consumer exists, that is a finding and a Blocked-by: relationship, not something you fix.

    PM 机制假设 (measure — falsifying these is a good run)

    The card's in-repo measurement is unusually well-controlled (97 sys_position-naming files read; positive controls active, delegatable, is_default, name all resolving to real readers; cross-object controls valid_until, granted_by). Re-derive it anyway — it was taken at origin/main@07bfd31cb and today is 2d3860df9. ⚠️ Note the card's own warning that the bare token permissions collides generically (441 files), so the object-scoped second pass is the load-bearing one; ⛔ do not "confirm" it with a whole-tree grep.

    ⚠️ This container is a depth-50 shallow clone — use git show origin/main:<path> / git grep … origin/main, ⛔ never git log for history. Anchor by symbol, not line number (:196 and :118 are from the census ref).

    ⛔ Two fences

    • Governed surface: ⛔ do not write docs/adr/**. If the ADR-0087 conversion needs an ADR entry authored, draft it in the PR body and flag it — the maintainer authors it.
    • Removing a published authorable column is a real retirement, not a deletion. If the playbook's ceremony turns out to exceed one card — or if the ledger verdict does not confirm dead — report needs_decision and stop rather than half-executing it. That is a complete delivery. (Precedent worth knowing: on FieldSchema accepts deleteBehavior: 'set_null' on a master_detail, and the engine silently resolves it to cascade #9689 a dev was sent to this same playbook and correctly found §0 did not apply to its case; following the instruction literally would have red-gated. Read the playbook against this key's facts.)

    Premise-first

    The body is a clue, not a spec. premise_still_valid: false is a legitimate delivery — if a producer or reader has landed since the census, that finding outranks the ruling's shape and you should report it rather than deleting anyway.

    Final report: structured JSON report contract, returned AND posted here with first line <!-- os-dev-report -->. Machine-checkable fields only.


    Generated by Claude Code

  7. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor
    {
      "issue": 9885,
      "status": "done",
      "branch": "claude/issue-9885-retire-sys-position-permissions",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/10182",
      "premise_still_valid": true,
      "summary": "Removed sys_position.permissions and the clone_position defaultFromRow copy entry per the 2026-08-20 ruling. FIRST STEP as directed: objectui consumer check via git clone (HEAD fd227eae1d33, API 403 not treated as absence) — 31 sys_position-naming files, zero consumers of the column, positive controls name/label/managed_by resolve to real readers under the identical instrument; no curated field list or designer names it, clone_position absent there. Census re-derived at origin/main cc21aad8ed: zero producers, zero readers, controls resolve — premise valid. Route read against this key's facts (#9689 lesson): PositionSchema never declared the key, so this is a platform-object COLUMN retirement on the ups-delegated-from-column-retired precedent — D3 semantic entry position-permissions-column-retired under major 17, nothing in RETIRED_KEYS_BY_MAJOR, no liveness row (ledger walks PositionSchema's shape; a row would be an ORPHAN — that is the ledger-verdict confirmation, with the re-derived census as the dead measurement), surface ratchets byte-identical as the route expects. Riders: locale bundles regenerated via os i18n extract (exactly 4 leaves removed), regenerated registry/spec-changes/upgrade-guide projections, removal pin tests with a positive control, minor+BREAKING changeset for plugin-security+spec stating the accept-set narrowing plainly, adr-0087 marker registered. Judgment call flagged in the PR body: added a PositionSchema strict-parse guidance entry for `permissions` (the mechanism's documented purpose is tombstones for retired keys) — one hunk to drop if judged out of scope. docs/adr/** untouched; no new ADR entry needed. CI status at report time: in_progress (report delivered at draft-PR time per contract).",
      "tests": "All at head bba754b (final commit; nothing changed after). pnpm --filter @objectstack/spec test: 'Test Files 414 passed (414) / Tests 11041 passed (11041)'. pnpm --filter @objectstack/plugin-security test: 'Test Files 66 passed (66) / Tests 1303 passed (1303)'. Honesty note per #10166: the appended '-- --maxWorkers=2' was swallowed by pnpm, so both runs were FULL package suites — stronger coverage than intended, ~6.5min lock hold; lesson taken. Playbook gate battery, redirect-then-capture per gate (no pipes): check:migration-registry, check:spec-changes, check:upgrade-guide, check:authorable-surface, check:liveness, check:empty-state, check:docs, check:api-surface, check:variant-docs, check:skill-refs, check:skill-docs, check:skill-examples, spec typecheck, plugin-security typecheck = 14/14 PASS. dispatch-gates.mjs (no path args, derived from real diff incl. changeset) union = 22/22 PASS incl. convention-triggered check:query-options-erasure, check:type-check-coverage, check:type-check-debt (after the full packages closure build it requires), check:engine-double-contract, check:where-matcher, check:i18n, and check-adr-0087-registration / check-changeset-no-major / check-empty-changeset. check-nul-bytes: OK. Ratchet dirs authorable-surface/api-surface/json-schema.manifest: byte-identical (expected for this route per the delegated_from precedent). No ablation legs were run: the pins are direct structural assertions on in-package src imports (relative './index.js', no dist resolution), and no schema member with expression surface was deleted, so no rebuild-dependent leg exists in this diff.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  8. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    os-dev-report
    (previous comment 5356238646 is this same report; its HTML-comment marker was eaten by the sanitizer, so this copy carries the literal marker line the scan needs)

    {
      "issue": 9885,
      "status": "done",
      "branch": "claude/issue-9885-retire-sys-position-permissions",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/10182",
      "premise_still_valid": true,
      "summary": "Removed sys_position.permissions and the clone_position defaultFromRow copy entry per the 2026-08-20 ruling. FIRST STEP as directed: objectui consumer check via git clone (HEAD fd227eae1d33, API 403 not treated as absence) — 31 sys_position-naming files, zero consumers of the column, positive controls name/label/managed_by resolve to real readers under the identical instrument; no curated field list or designer names it, clone_position absent there. Census re-derived at origin/main cc21aad8ed: zero producers, zero readers, controls resolve — premise valid. Route read against this key's facts (#9689 lesson): PositionSchema never declared the key, so this is a platform-object COLUMN retirement on the ups-delegated-from-column-retired precedent — D3 semantic entry position-permissions-column-retired under major 17, nothing in RETIRED_KEYS_BY_MAJOR, no liveness row (ledger walks PositionSchema's shape; a row would be an ORPHAN — that is the ledger-verdict confirmation, with the re-derived census as the dead measurement), surface ratchets byte-identical as the route expects. Riders: locale bundles regenerated via os i18n extract (exactly 4 leaves removed), regenerated registry/spec-changes/upgrade-guide projections, removal pin tests with a positive control, minor+BREAKING changeset for plugin-security+spec stating the accept-set narrowing plainly, adr-0087 marker registered. Judgment call flagged in the PR body: added a PositionSchema strict-parse guidance entry for `permissions` (the mechanism's documented purpose is tombstones for retired keys) — one hunk to drop if judged out of scope. docs/adr/** untouched; no new ADR entry needed. CI status at report time: in_progress (report delivered at draft-PR time per contract).",
      "tests": "All at head bba754b (final commit; nothing changed after). pnpm --filter @objectstack/spec test: 'Test Files 414 passed (414) / Tests 11041 passed (11041)'. pnpm --filter @objectstack/plugin-security test: 'Test Files 66 passed (66) / Tests 1303 passed (1303)'. Honesty note per #10166: the appended '-- --maxWorkers=2' was swallowed by pnpm, so both runs were FULL package suites — stronger coverage than intended, ~6.5min lock hold; lesson taken. Playbook gate battery, redirect-then-capture per gate (no pipes): check:migration-registry, check:spec-changes, check:upgrade-guide, check:authorable-surface, check:liveness, check:empty-state, check:docs, check:api-surface, check:variant-docs, check:skill-refs, check:skill-docs, check:skill-examples, spec typecheck, plugin-security typecheck = 14/14 PASS. dispatch-gates.mjs (no path args, derived from real diff incl. changeset) union = 22/22 PASS incl. convention-triggered check:query-options-erasure, check:type-check-coverage, check:type-check-debt (after the full packages closure build it requires), check:engine-double-contract, check:where-matcher, check:i18n, and check-adr-0087-registration / check-changeset-no-major / check-empty-changeset. check-nul-bytes: OK. Ratchet dirs authorable-surface/api-surface/json-schema.manifest: byte-identical (expected for this route per the delegated_from precedent). No ablation legs were run: the pins are direct structural assertions on in-package src imports (relative './index.js', no dist resolution), and no schema member with expression surface was deleted, so no rebuild-dependent leg exists in this diff.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  9. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    ✅ ACCEPT — PR #10182. Reviewer of record: seat #6023, session session_01DdCnBGcHeufjrq7drTD3wt, 2026-08-20T13:0xZ (date -u).

    Ruling on the flagged judgement call first: KEEP the PositionSchema guidance hunk. ⛔ Do not drop it. Reasoning below.

    ⭐ The objectui consumer check was done properly, and I re-ran it

    This was the ruling's named first deliverable and the card's one real evidence gap. It was done by clone, not by treating the API's 403 as an absence:

    /workspace/objectstack-ai/objectui  HEAD fd227ea  origin …/objectui   ← matches the reported clone
    31 files name sys_position                                            ← matches the reported count exactly
    

    I re-derived the negative myself, and it took two attempts, which is worth recording: my first instrument returned zero for permissions AND zero for the positive controls name/label/managed_by — a broken regex, so that negative proved nothing. Re-run as "grep permissions inside the 31 files that name sys_position", with a control that fires: 17 files co-mention both, and every hit is unrelated —

    • @object-ui/permissions package imports, usePermissions / useFieldPermissions / MePermissionsProvider
    • the system/permissions route, which AppContent.tsx:137 explicitly maps to sys_permission_set
    • SystemHubPage's permissions: count bucket (countOrUnknown(permsRes) — permission sets)
    • requiredPermissions, an action-bar prop; and one prose comment

    ⇒ Zero consumers of sys_position.permissions in objectui. Confirmed. ⭐ And the console's own routing is corroborating evidence for the card's thesis: it sends "permissions" to permission sets, because that is the only real grant path.

    ⭐ The route was read against THIS key's facts, not by analogy

    I warned about the #9689 precedent — a dev sent to this playbook that found §0 did not apply, where following the instruction literally would have red-gated. That warning paid off in the opposite direction: the playbook was followed, but only after establishing which route this key is on.

    PositionSchema never declared permissions (verified: zero hits on origin/main). So this is a platform-object column retirement on the ups-delegated-from-column-retired precedent, not a spec-key retirement:

    • D3 semantic entry position-permissions-column-retired under major 17 ✅
    • nothing in RETIRED_KEYS_BY_MAJOR — correct, the key was never a schema key
    • no liveness row — the ledger walks PositionSchema's shape, so a row would be an orphan. ⭐ That reasoning is the ledger-verdict confirmation the ruling asked for, with the re-derived census as the dead measurement
    • surface ratchets byte-identical, as that route predicts

    The removal is complete and tombstoned

    sys-position.object.ts drops exactly the two things the ruling named — the permissions: Field.textarea({…}) declaration and the { field: 'permissions', defaultFromRow: true } clone_position copy entry (that params block is now label / name / description only). The three surviving permissions mentions in the file are: one unrelated confirmText phrase and two dated tombstone comments. ⛔ No residue.

    Ruling: the guidance hunk stays

    The dev offered to drop it. It is the strongest part of the retirement and it is in scope. The text is honest about its own status — it opens "permissions is not a Position field", so it does not imply the schema ever accepted the key — and it carries the prescription: capability reaches a position only through sys_position_permission_set bindings; delete the key and bind a set instead.

    Why it belongs: the card's own four-axis analysis says the harm is that "the declared textarea tells an AI author 'grant permission strings directly on a position' — a capability the runtime does not have." Removing the column closes the declaration, but an agent working from a cached example, an older app definition, or training data will still write permissions — and would get a bare strict-parse rejection with no explanation. The guidance entry is what makes the removal teach instead of merely refuse, which is the "响亮拒绝" axis rather than a silent one. It also sits in an existing guidance map beside a sibling entry, so it follows the file's pattern rather than inventing one.

    Gates and honesty

    14/14 playbook battery + 22/22 dispatch-gates union (self-derived from the real diff, so it reached beyond my dispatch list — including check:type-check-debt after the full closure build, check-adr-0087-registration, check-changeset-no-major). Locale bundles regenerated via os i18n extract with exactly 4 leaves removed. minor + BREAKING changeset across plugin-security + spec stating the accept-set narrowing plainly. docs/adr/** untouched, as fenced.

    ⚠️ Docs: no rider needed, and that is measured. The drift bot flagged three hand-written permission pages. I read all three: every permissions occurrence is a permission set, systemPermissions, stack.permissions, or requiredPermissions. No page ever documented the removed column — the rows fired on the sys_position symbol. The four release-owned pages were correctly left read-only.

    ⭐ No ablation legs, with a structural reason rather than a shrug: the pins are direct structural assertions over in-package relative src imports with no dist resolution, and no schema member with expression surface was deleted — so there is no rebuild-dependent leg for an ablation to defeat. Declaring why a verification step does not apply is the right move; silently omitting it is not.

    ⚠️ #10166 hit again, self-reported: the appended -- --maxWorkers=2 was swallowed, so both suites ran full (~6.5 min lock hold). Stronger coverage than intended, and the honesty note is the right response — but this is now the third independent reproduction today, which strengthens #10166's case considerably.

    ⚠️ Sanitizer ate the report marker again (5356238646 → re-posted as 5356243897 with a literal marker). Second confirmed instance today. Any collector grepping for that marker will miss reports; marker-absence ≠ report-absence.

    Disposition

    ACCEPT. ⚠️ This PR does trip Clause ②'s path limb — packages/spec/src/identity/position.zod.ts and three siblings under packages/spec/src/**. It is still enqueueable, because the gate fires only when a limb hits and the dispatch tier is below CONTRACT_REVIEW_TIER; this ran at it (claude-fable-5). ⇒ No needs:contract-review owed. ⭐ Third card this round whose legality rests on that dispatch decision.

    ⛔ Not flipping ready until CI converges; then ready → auto-merge → enqueue verified against refs/heads/gh-readonly-queue/main/*.

    ⚠️ Note for the domain:spec seat (#6017): this lands 4 files in packages/spec/src/** — a semantic migration entry, the registry, position.zod.ts and its test. Filed under a domain:services card by maintainer direct-dispatch; flagging rather than assuming it is unwelcome.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions