← all branches

exp/core-dossiers

needs attentionviewing older commit
a516a9d · incrementalPR #270reviewed 2026-07-17 04:38 UTC4H · 5M · 4L · 3I
The branch
Purpose
Stand up a capability-dossier knowledge system for the FE + public-API surface (the projection that backend ontology/FCIS docs never covered), and populate it with 9 audited core-domain dossiers.
Goal
Replace the 'dossier as enforcement gate' model with 'dossier as assistive map + mechanical lint fence', add the FCIS-boundary ESLint rule as the real enforcement wall, and preserve the audit artifacts separately from living dossiers.
Sub-goals
  • SG-1: Demote capability-dossier.md from blocker/gate to assistive reference
  • SG-2: Add FCIS-boundary ESLint rule (warn) to apps/platform/eslint.config.mjs targeting handlers/
  • SG-3: Add audit/ subdirectory with canonical-api-form + per-entity audit snapshots
  • SG-4: Refine V1 finding — coordinator pattern is NOT a bug; only profile signup (BAT-269) is real
  • SG-5: Strip check-freshness machinery (Mode D) from dossier skill
The changes (whole branch)
What
Pivoted the dossier system from 'enforcement gate' to 'assistive map'. Added the first mechanical FCIS-boundary lint rule (warn). Added audit/ subfolder with canonical API form doc + 6 per-entity audit snapshots. Stripped YAML front-matter from 8 entity dossiers. Refined V1 bug finding to narrow from 4 suspected violations to 1 confirmed (profile only). Removed Mode D (freshness check).
Why
The freshness-gate model was fragile (pnpm dossier:check was never wired into CI; the 'same PR blocker' language was not enforceable). Moving enforcement to mechanical lint (ESLint FCIS-boundary rule) creates a real, code-level fence while keeping dossiers as high-signal, human-curated reference docs.
Areas
.claude/rules+1346.claude/skills/dossier/references/audit+9930.claude/skills/dossier/references/entities+1691.claude/skills/dossier/references+2516.claude/skills/dossier+1529apps/platform+450
Blast
22 files, +2552/-0 cumulative vs main; this commit +1107/-182. Zero runtime changes — all .claude/ docs + one eslint config. No migrations, no domain code, no API contracts touched.
docs-only dx-tooling zero-runtime-change
CI / pr-checks· No CI check results returned by gh pr checks — checks may not have run yet for this SHAcoderabbit· No .coderabbit.yaml in repocheck-freshness.mjs· Removed in this commit; was never wired into CI anyway

Findings · 16

correctness5

high

_audit-index.md contradicts _findings.md V1 on membership — same commit, opposite verdicts

.claude/skills/dossier/references/audit/_audit-index.md:12

_audit-index.md (new in this commit) labels 'createMembershipShell has zero callers' as a hard blocker (V1 dead create shell). _findings.md (also updated in this commit) explicitly says this is NOT a bug: 'Coordinators legitimately compose decisions + write the outbox directly.' Same commit ships both — readers will see contradictory verdicts on the same code path. The audit/membership.md also repeats the pre-refinement verdict at line 39.

medium

no-restricted-imports doesn't catch barrel re-export imports (actual violation pattern in use)

apps/platform/eslint.config.mjs:88

The patterns ['**/*.queries', '**/*.queries.*', '**/queries/*'] only catch direct filesystem imports ending in .queries. Real violations import from FCIS/domain barrels (e.g. '@batu/utility-domain/cfe-job') — these don't match the pattern. The no-restricted-syntax call-site selector compensates, but the import-level gate provides no additional coverage and may give false assurance.

low

ESLint comment references non-existent 'fix-strat' document — dangling pointer

apps/platform/eslint.config.mjs:67

Line 67: 'handled by the fix-strat' — no file named fix-strat exists in the repo. The reference is a dangling pointer. A reader cannot locate the referenced strategy.

info

ESLint AST selectors are correctly formed and match the intended violation patterns

apps/platform/eslint.config.mjs:76

Both selectors verified via AST: selector 1 (callee.object.name=/[Qq]ueries$/) correctly matches `jobQueries.update(...)`. Selector 2 (callee.object.property.name=/[Qq]ueries$/) correctly matches `ProfileFCIS.profileQueries.insert(...)`. The ~6 existing hits count is accurate. esquery regex attribute support is confirmed in installed version.

info

V1 refinement in _findings.md is factually correct — coordinator outbox writes confirmed

.claude/skills/dossier/references/_findings.md:8

All three 'NOT a bug' claims are code-verified: invitation.shells.ts:290 emits core.member.added in-transaction; organization-with-owner.shell.ts:165 emits core.member.added; site-with-devices-provisioning.shells.ts:512 emits core.site.created. The profile case (auth.handler.ts:270,295) has no core.profile.created emission — confirmed real bug, correctly the only V1 violation.

security3

high

Dynamic import() in cfe-jobs-internal handler bypasses no-restricted-imports entirely

apps/platform/src/api/handlers/cfe-jobs-internal.handler.ts:261

The handler uses `const { jobQueries } = await import('@batu/utility-domain/cfe-job')` at runtime then calls `jobQueries.update(database, ...)` at line 262. ESLint's no-restricted-imports is static analysis only — it cannot see dynamic import() expressions. The import restriction is bypassed entirely. The no-restricted-syntax call-site selector does catch `jobQueries.update(...)` as a warn, but the import gate is silently skipped.

high

V5 authz divergence (contexts handler enforces member, contract declares admin/owner) — live, unaddressed

apps/platform/src/api/handlers/contexts.handler.ts:97

All five context write operations (create/update/delete context, create/delete relationship) have contract docstrings declaring 'RBAC: Must be admin or owner' but every handler enforces only requireOrgAccess(..., 'member'). Any org member can create/delete contexts. Tracked in _findings.md as V5 (NEEDS-HUMAN) and _canonical-api-form.md, but not addressed in this commit. Context has no FE surface today but the API is callable.

low

apiKeyQueries.updateLastUsedAt called directly in public API handler — fire-and-forget shell bypass

apps/platform/src/api/handlers/public-v1/auth-token.handler.ts:139

Direct query mutation (.catch() fire-and-forget) in a public API handler. The no-restricted-syntax rule does flag this (starts with 'update') but as warn only. Low stakes for last-used-at tracking, but documents the class of issue the rule is designed to catch.

conventions4

high

_index.md not updated to reference new audit/ directory

.claude/skills/dossier/references/_index.md

A new references/audit/ directory with 8 files was added but the master index _index.md was not updated. SKILL.md Rule 5 states 'Update _index.md on every Build/Refresh. The index is the discovery surface.' The audit directory is completely undiscoverable from the index.

medium

warn→error promotion references undocumented 'fix-strat' with no ticket or measurable condition

apps/platform/eslint.config.mjs:65

'Promote to error once the fix-strat routes them through shells' — 'fix-strat' exists nowhere in the repo (confirmed by grep). No Linear ticket, no definition of done (zero hits? BAT-269 closed?). The React Compiler rules show the risk: they've been at warn since they landed with the same 'sweep + promote' intent. Add a BAT ticket reference and a concrete measurable condition.

medium

capability-dossier.md (Tier 2 rule) cross-links into Skill internals (Tier 4)

.claude/rules/capability-dossier.md:79

The enforcement footer links to .claude/skills/dossier/references/audit/_canonical-api-form.md — a file inside a Skill (Tier 4, on-demand). Tier 2 rules should be self-contained or reference Tier 1/2 paths; depending on Skill internals creates a fragile cross-tier dependency. If _canonical-api-form.md is intended as a Tier 2 reference it should live in .claude/rules/, not inside a skill's references/audit/ subdirectory.

low

_audit-index.md uses plain-numeral patterns (1–10) inconsistently with V-prefix taxonomy

.claude/skills/dossier/references/audit/_audit-index.md:21

_findings.md uses V-prefix (V1–V6) per the prior rename from P→V. _audit-index.md introduces 10 canonical patterns with plain numerals only. The taxonomy is inconsistent across two files introduced in the same commit.

tests1

info

check-freshness.mjs / Mode D was never wired into CI — removal does not weaken gates

.claude/skills/dossier/SKILL.md

Grep across all .github/workflows/ files finds no reference to pnpm dossier:check or check-freshness. The prior pr-checks.yml step described in capability-dossier.md never existed. Removal is a clean docs-only consistency fix — no CI gate was lost.

improvement3

medium

audit/*.md files lack 'snapshot, not living reference' disclaimer

.claude/skills/dossier/references/audit/_audit-index.md

Entity dossiers in entities/*.md are updated via Mode C (Refresh) when the surface changes. The audit/*.md files are one-time Week-1 canonicalization snapshots. There is no prominent header warning that these files are NOT kept current by Mode C. A future agent or reader running a refresh may mistake them for authoritative current-state documents. Add: 'Snapshot: 2026-07-14. Not updated on code changes — consult entity dossier for current state.'

medium

Entity dossier front-matter removal breaks machine-readability without documented replacement

.claude/skills/dossier/references/entities/profile.md

All 8 entity dossiers had contracts: and hooks: YAML front-matter stripped. The audit/*.md files still carry contracts:/shells:/hooks: front-matter (asymmetric). A Mode C refresh agent that previously read entity front-matter to know which files to rescan now has no structured entry point — must parse §1 prose tables. If audit front-matter is the intended machine-readable surface going forward, document this asymmetry so future agents don't look for front-matter in entity dossiers.

low

_findings.md V1 refinement ('must fire event' not 'must call shell') not reflected in entity dossier §4

.claude/skills/dossier/references/entities/membership.md

Entity dossiers for membership and organization may still describe the shell-call heuristic in §4. The membership dossier's §4 notes 'createMembershipShell has zero callers' as a V1 finding — which _findings.md now says is NOT a violation. Entity §4 sections were not synchronized with the V1 refinement.

History · 7 commits

  1. 8ff8773needs attentionincremental1H · 3M · 2L2026-07-27 17:46
  2. 7640070needs attentionincremental10H · 18M · 14L2026-07-18 02:11
  3. a516a9dneeds attentionincremental4H · 5M · 4L2026-07-17 04:38current
  4. 910fc6aneeds attentionincremental1H · 9M · 6L2026-07-10 23:48
  5. 0b75850safeincremental0H · 0M · 0L2026-07-10 23:17
  6. 380a931safeincremental0H · 0M · 0L2026-07-09 19:17
  7. 5a9ac90blockedfull5H · 8M · 5L2026-07-07 22:07