{"uuid": "6bba259b-b565-4b31-af8b-99ca01202f32", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2021-42574", "type": "seen", "source": "https://gist.github.com/serpi4/aba8a4ee71a0b5033f1f2918195fdd95", "content": "# dev-signals \u2192 dev-a substrate reconciliation \u2014 survey of 12 candidate predicates\n\n**Purpose**: facilitate decision on Option (3) \u2014 bulk reconcile vs sequential re-lift \u2014 by surveying what's actually in the dev-signals substrate.\n\n**Date**: 2026-05-10\n**dev-a tip**: `10defe8c` (3 predicates: FF-22/23/46)\n**dev-signals tip**: `594d3368` (14 predicates: FF-22 + 13 unique)\n**Subject of immediate Q**: FF-39 (excluded from this survey \u2014 assessed separately)\n**Survey target**: 12 dev-signals-only predicates (FF-28/29/34/35/36/37/38/40/41/42/43/45) + a note on FF-22 divergence\n\n&gt; **Why 12 and not 11**: the original Q referenced \"remaining 11\"; counting the actual dev-signals-only set yields 12 (excluding FF-39 + FF-22-which-is-on-both). FF-22 also has a 217-line divergence between dev-a and dev-signals \u2014 included as Annex A.\n\n---\n\n## TL;DR\n\n| Bucket | FFs | Recommendation |\n|---|---|---|\n| **A. Strong-architectural** (clear AC candidate, anchor incidents, generalizing principle) | FF-40, FF-42, FF-43, FF-45 | Port with adaptation \u2014 high signal, modest re-derivation cost |\n| **B. Medium-architectural** (architectural in spirit, but heuristic classification or domain-leaning) | FF-28, FF-29, FF-34, FF-36 | Port if the matching AC slot exists \u2014 lift gate Q1/Q2 will likely pass |\n| **C. Borderline / process-flavored** (might fail Q1 \"is it architectural?\" or Q3 \"anchor evidence?\") | FF-35, FF-37, FF-38, FF-41 | Architectural-lift gate first; some likely demote to integration tests / ADRs / process-FFs |\n| **Subject** | FF-39 | Pick (1) or (2) per separate convo; this gist informs the (3) frame |\n\n**Bucket A** alone is ~5 days of port work (saves ~20+ days of from-scratch lift).\n**Bucket A+B** is ~11 days port (saves ~40+ days from-scratch).\n**Bucket C** likely 1-2 demote out of the lift entirely.\n\n---\n\n## Quick stats (dev-signals predicates)\n\n| FF | LOC | Tier | Kind | Coverage | Scope | Anchor incidents |\n|---|---:|---|---|---|---|---|\n| FF-22 | 273+217=490 | regex | (n/a, on dev-a) | cross-cutting | atomic | TASK-4173, TASK-4204 |\n| FF-28 | 265 | regex | trend (implicit) | cross-cutting | atomic | B1 typo, /admin/ops/* (lessons-learned 2026-04-27) |\n| FF-29 | 164 | regex | trend (implicit) | cross-cutting | holistic | EventOpsNavBlock drop (2026-04-27, ~7d undetected) |\n| FF-34 | 308 | regex | **tripwire** | domain-specific | holistic | TASK-4161, TASK-4291 (ADR-046) |\n| FF-35 | 183 | ast-grep | **tripwire** | domain-specific | atomic | TASK-4307 (ADR-048) |\n| FF-36 | 245 | ast-grep | trend (implicit) | cross-cutting | holistic | (none \u2014 preventive) |\n| FF-37 | 283 | ast-grep | trend (implicit) | cross-cutting | holistic | (none \u2014 preventive) |\n| FF-38 | 501 | ast-grep | trend (implicit) | cross-cutting | holistic | (none \u2014 preventive) |\n| FF-39 | 385 | regex | (subject) | cross-cutting | holistic | (none cited) |\n| FF-40 | 327 | ast-grep | trend (implicit) | cross-cutting | holistic | (none \u2014 preventive, ADR-005) |\n| FF-41 | 276 | fs-walk | trend (implicit) | cross-cutting | holistic | (none \u2014 process-FF) |\n| FF-42 | 251 | regex | **tripwire** | cross-cutting | atomic | ZWSP/ICU translator copy-paste class, CVE-2021-42574 |\n| FF-43 | 185 | fs-walk | **trend** (declared) | cross-cutting | holistic | 2026-04-29 ID collision crisis (TASK-4250..4254) |\n| FF-45 | 249 | regex | **trend** (declared) | cross-cutting | holistic | 2026-04-29 retro (no-build-id forensics gap) |\n\n**Total dev-signals-only LOC**: 3,622 across 13 predicates (avg 279 LOC each)\n**Total fixtures across 12 surveyed**: 117 corpus files\n\n---\n\n## Per-FF assessment\n\n### Bucket A \u2014 Strong-architectural (port with high confidence)\n\n#### FF-40 \u2014 BC Coupling Trend (LOC-weighted isolation gradient)\n- **Principle**: ADR-005 \u2014 no cross-BC value imports. Generalizes to \"every BC is a clean island\" \u2014 same shape as Conway's Law decoupling, hexagonal-arch port boundaries.\n- **AC candidate**: **AC-04 \u2014 Module-Boundary Discipline** (charter has placeholder \"Module-boundary discipline \u2014 backed by FF-01, FF-40\").\n- **Lift gate verdict**: PASS. Q1 architectural \u2713 (cross-BC coupling is universal arch concern). Q2 generalizes \u2713 (all 6 BCs). Q3 anchor evidence \u2014 **WEAK** (no specific incidents cited; preventive). Q4 falsifiable \u2713. Q5 escapable via SAFE annotation \u2713. Q6 detector tier appropriate \u2713.\n- **Port effort**: 1-2 days. Logic is solid; needs `kind: 'trend'` declared, AC-04 charter entry, anchor-incident hunt (look at FF-01 v1 violations for backfill).\n- **Note**: substantial overlap with FF-36 (cross-BC events) \u2014 same imports, different scoring. Decide if both port or pick one.\n\n#### FF-42 \u2014 Invisible Unicode Detector\n- **Principle**: source files must contain only printable+intentional characters. Maps to **AC-05 \u2014 Source Integrity / Trojan-Source Defense** (would be a NEW AC).\n- **Lift gate verdict**: PASS. Q1 \u2713 (security boundary, CVE-2021-42574 class). Q2 \u2713 (any source file). Q3 \u2713 (translator copy-paste class, ZWSP equality bugs). Q4 \u2713 (lexical detection). Q5 \u2713 (SAFE annotation). Q6 \u2713 (regex tier appropriate).\n- **Port effort**: 1 day. Already declared `kind: 'tripwire'`. Needs new AC-05 charter entry.\n- **Strongest case in the survey** \u2014 clear bug class, framework-agnostic principle, cheap detection.\n\n#### FF-43 \u2014 Backlog Ticket-ID Uniqueness (trend)\n- **Principle**: ID-space integrity for the project's traceability spine. Maps to **AC-06 \u2014 Traceability** (charter has placeholder \"Traceability \u2014 backed by FF-25, FF-26, FF-43\").\n- **Lift gate verdict**: PASS-with-note. Q1 architectural \u2713 (traceability is a quality attribute per Ford ch.2). Q2 \u2713 (whole backlog). Q3 \u2713 (2026-04-29 collision crisis). Q4 \u2713 (filename detection). Q6 \u2713 (fs-walk).\n- **Note**: technically a **process-FF / Ford-canonical** (not code-architecture). Charter entry would explain that distinction.\n- **Port effort**: 0.5 day. Already declared `kind: 'trend'`. Needs AC-06 entry consolidating with FF-25/26.\n\n#### FF-45 \u2014 Build-Version Exposure (ADR-034 \u00a75)\n- **Principle**: deployed images must be self-identifying for incident forensics. Maps to **AC-07 \u2014 Diagnosability** (charter has placeholder \"Diagnosability \u2014 backed by FF-27, FF-45\").\n- **Lift gate verdict**: PASS. Q1 \u2713 (observability/diagnosability is a textbook architectural characteristic). Q2 \u2713 (every Docker build site). Q3 \u2713 (2026-04-29 retro, build-id forensics gap). Q4 \u2713 (regex). Q6 \u2713.\n- **Port effort**: 1 day. Already declared `kind: 'trend'`. Needs AC-07 entry.\n\n**Bucket A total**: ~4 days port + 4 new AC entries + ~36 corpus fixtures preserved.\n\n---\n\n### Bucket B \u2014 Medium-architectural (port if AC slot exists)\n\n#### FF-28 \u2014 Admin HREF Validity\n- **Principle**: framework-mounted route table is the truth; static hrefs must agree. Maps to existing **AC-02 (Admin-List Primary-Column Navigability)** as a peer invariant, OR a new \"Admin UI Surface Integrity\" AC consolidating FF-28/29.\n- **Lift gate verdict**: PASS. Q1 \u2713 (mental-model-drift class generalizes). Q2 \u2713 (cross-BC). Q3 \u2713 (B1 typo, /admin/ops/* drops). Q4-Q6 \u2713.\n- **Port effort**: 1.5 days. Route registry needs refresh (hardcoded snapshot from 2026-05-03 \u2014 likely already stale on dev-a). No `kind:` declared \u2192 needs `tripwire` (each broken href = silent regression).\n- **Risk**: route registry maintenance cost \u2014 every collection slug change requires an update. Could be auto-derived from payload.config.ts.\n\n#### FF-29 \u2014 Admin Shell Wiring\n- **Principle**: components that don't get referenced from config are dead. Companion to FF-19. Same AC slot as FF-28 (Admin UI Surface Integrity).\n- **Lift gate verdict**: PASS. Q1 \u2713. Q2 \u2713 (any shell component). Q3 \u2713 (EventOpsNavBlock incident). Q4-Q6 \u2713.\n- **Port effort**: 1 day. Probably consolidate with FF-28 into one \"admin-config-vs-code drift\" lift.\n\n#### FF-34 \u2014 Invariant Parity (ADR-046 cross-layer enforcement)\n- **Principle**: if you publish a pure invariant module, it must be consumed by both server hooks AND client UI (otherwise bare PATCH bypasses the gate). **Already declared `kind: 'tripwire'`**.\n- **AC candidate**: NEW \u2014 **AC-08 \u2014 Cross-Layer Enforcement Discipline** (would map to \"tripwire FF for ADR-046 violations\"). Or fold into a broader \"Approval Pipeline Input Fidelity\" extension (AC-01 already exists for FF-46 \u2014 but that's about preservation, not parity).\n- **Lift gate verdict**: PASS, but Q1 is borderline. Axes declares `coverage: 'domain-specific'` \u2014 acknowledging the rule is project-specific (ADR-046 + ADR-006). Q2 generalizes across BCs \u2713 (any pure-invariant module). Q3 \u2713 (TASK-4161, TASK-4291).\n- **Port effort**: 2 days. Architectural-lift gate Q1 will need defense \u2014 \"is this architectural or domain?\" The principle (cross-layer enforcement of pure functions) is architectural; the specific mechanism (ADR-046 module convention) is project-specific. Frame it as ADR-046 \u2192 arch char.\n\n#### FF-36 \u2014 Cross-BC Event Coverage\n- **Principle**: cross-BC interactions must mediate via eventBus, not direct imports. Same AC-04 as FF-40 (or sibling).\n- **Lift gate verdict**: PASS. Q1-Q6 mirror FF-40.\n- **Port effort**: 1.5 days. **Note overlap with FF-40** \u2014 they detect the same import pattern but score differently (FF-36 = D/(D+E), FF-40 = LOC-ratio). Worth deciding if both add signal or one is redundant.\n\n**Bucket B total**: ~6 days port if all four ported; could collapse to ~4 days if FF-28+29 merged and FF-36/40 merged.\n\n---\n\n### Bucket C \u2014 Borderline / process-flavored\n\n#### FF-35 \u2014 State-Transition Idiom (ADR-048)\n- **Principle**: `dispatchFields` is racy under React 18 batching \u2192 use `submit({ overrides })`. Already declared `kind: 'tripwire'`.\n- **Lift gate verdict**: BORDERLINE. Q1 \u2014 the rule is **specific to one Payload UI primitive in one BC pattern** (admin gate components). Q2 generalizes across \"transition fields\" but only within Payload admin gates. The principle (avoid stale-snapshot reads) is architectural; the specific manifestation is narrow.\n- **Recommendation**: **lift gate first** \u2014 likely demotes to ADR-048 enforcement test, not a top-level FF. Or keep as a tripwire under a \"React Concurrency Discipline\" AC if other patterns surface.\n- **Port effort if kept**: 1 day.\n\n#### FF-37 \u2014 Hook Side-Effect Declarativeness\n- **Principle**: hooks should be EMITS / AUDIT_WRITES / PURE / OPAQUE; declarative ratio measures architectural debt.\n- **Lift gate verdict**: BORDERLINE. Q1 \u2014 declarativeness IS an architectural characteristic. Q3 \u2014 **no anchor incidents cited**. Q4 \u2014 classification heuristic is fragile (e.g., \"import-anchored publish() detection\" can false-positive/negative).\n- **Recommendation**: lift gate first. Likely outcome: defer until anchor incidents surface OR demote to \"hook code review checklist\" via `.claude/skills/`. The 4-class classification has subjective edges.\n- **Port effort if kept**: 2 days.\n\n#### FF-38 \u2014 Access Control Completeness\n- **Principle**: scope filters (Where conditions) are stronger than role-only checks. Score = STRONG / total.\n- **Lift gate verdict**: BORDERLINE. Q1 \u2713 (security boundary). Q3 \u2014 **no anchor incident**; this is a preventive gradient. Q4 \u2014 STRONG vs ROLE_ONLY classification is heuristic and false-positive prone (e.g., a role check inside `where:` clause might miscount). Q6 \u2014 501 LOC suggests the heuristic is fragile.\n- **Recommendation**: lift gate first. Probably lands as report-only-forever \u2014 useful as a surveillance metric but not a tripwire. Could re-frame as ADR-009 enforcement audit.\n- **Port effort if kept**: 2 days. Highest LOC in the set.\n\n#### FF-41 \u2014 Invariant Test Coverage Gradient (per-BC)\n- **Principle**: every BC has \u22651 invariant test. Companion to FF-09.\n- **Lift gate verdict**: BORDERLINE. Q1 \u2014 this is a **process-FF** (Ford ch.2 \u00a7Coverage uses these for governance, not arch). Q3 no anchor incident. The principle (\"all BCs have tests\") is testing hygiene, not architectural integrity.\n- **Recommendation**: **probably DON'T port as architectural FF.** Either keep as a `kind: 'process'` (introduce that classifier), or demote to a CI gate alongside `pnpm test`.\n- **Port effort if kept**: 1 day.\n\n**Bucket C verdict**: 1-2 of these likely get demoted/deferred during the gate pass. Saves 4-6 days vs porting all.\n\n---\n\n## Recommended phasing IF (3) is chosen\n\n**Tier-1 Reconcile (sprint 1, ~5 days)** \u2014 port Bucket A:\n- FF-40 + FF-42 + FF-43 + FF-45\n- Charter additions: AC-04 (Module-Boundary), AC-05 (Source Integrity), AC-06 (Traceability), AC-07 (Diagnosability)\n- Single audit PR + 4 port PRs\n\n**Tier-2 Reconcile (sprint 2, ~6 days)** \u2014 port Bucket B:\n- FF-28+29 merged into one Admin Surface Integrity lift\n- FF-34 (cross-layer enforcement)\n- FF-36 (decide vs FF-40 overlap)\n- Charter: AC-08 + AC-09 (or consolidate into AC-04)\n\n**Tier-3 Reconcile (sprint 3, ~3 days)** \u2014 Bucket C lift-gate:\n- Run architectural-lift Q1-Q6 gate on FF-35/37/38/41\n- Output: Demote 1-2 to process FFs / ADR-only / regression tests; port the survivors\n- Likely: keep FF-35 (already tripwire-classified), demote FF-41 to process-FF, defer FF-37/38 until anchor incidents\n\n**Total Tier-1+2+3**: ~14 days for ~10 ported predicates + 5-6 new AC charter entries + ~110 corpus fixtures preserved.\n\n**Compare to from-scratch sequential** (the dev-a \"drop-and-rederive\" plan): ~5 days \u00d7 13 FFs = ~65 days at the FF-23 cadence. Net savings from (3): ~50 days.\n\n---\n\n## Decision matrix \u2014 (1) vs (2) vs (3)\n\n|  | (1) Port FF-39 only | (2) Rebuild FF-39 from scratch | (3) Reconcile substrates first |\n|---|---|---|---|\n| Time to ship FF-39 | ~1.5 days | ~4 days | ~6 days (1.5 audit + Tier-1 Bucket A includes FF-39) |\n| Strategy clarity | Low \u2014 repeats decision 12 more times | Medium \u2014 each FF gets fresh gate | **High** \u2014 decide once, execute |\n| Lift-gate value | Skipped retroactively | Applied per-FF | **Applied across substrate** \u2014 discovers patterns |\n| AC charter completeness | +1 entry (AC-04) | +1 entry (AC-04) | **+5-6 entries** (AC-04..09) |\n| Risk if FF-40/42/43/45 get stale | Low (will be re-lifted later) | Low | **Eliminates risk** \u2014 they all land |\n| PR count to clear backlog | 1 now + 12 later = 13 PRs | 1 now + 12 later = 13 PRs | 1 audit + ~10 port = ~11 PRs |\n| Effort cost if you only want FF-39 | **Lowest** | High | Highest (sunk cost on Bucket A/B even if you don't use them) |\n| Effort cost if you want full v2 | **Highest** (sequential drag) | Highest (rebuild \u00d7 13) | **Lowest** (~14 days vs ~65 days) |\n\n---\n\n## Annex A \u2014 FF-22 divergence\n\ndev-signals has a **217-line larger FF-22** than dev-a (490 LOC vs 273 LOC). dev-a's version is the architectural-lift output of PR #18537. dev-signals' version pre-dates it \u2014 likely has the calibration logic from PR #18410 sidecar phase 1 plus subsequent fixes.\n\n**Decision needed regardless of (1)/(2)/(3)**: which FF-22 wins on dev-a if dev-signals work ever merges? Recommend: dev-a's version (architectural-lift-gated) is canonical; dev-signals' version absorbs its delta into adversarial corpus fixtures or gets discarded.\n\n---\n\n## My recommendation\n\nIf the goal is **\"v2 substrate complete in &lt;1 month\"** \u2192 **(3) Reconcile**, executing Tier-1 first (covers FF-39 + 3 high-value Bucket A FFs).\n\nIf the goal is **\"FF-39 specifically because of an anchor incident I haven't surfaced yet\"** \u2192 **(1) Port**, then defer the rest until an actual incident demands a port.\n\nIf the goal is **\"force every FF through the architectural-lift gate ceremony\"** \u2192 **(2) Rebuild**, accepting the ~65-day re-lift cost.\n\nThe **Bucket A** FFs (FF-40/42/43/45) are unambiguously high-value \u2014 the question for (3) is mainly whether to take them now or accept they'll get sequentially re-lifted later anyway. Each month of delay = month of dev-signals work being increasingly stale (the sidecar branch hasn't been touched since 2026-05-04 PR #18410, and dev-a has diverged 57 commits ahead \u2014 including substantial test reorganization).\n", "creation_timestamp": "2026-05-10T19:16:47.000000Z"}