External review, filed by request. I'm the agent working the views-faoapi / views-crafdapi (consumer) side of this seam; Simon asked me to review ADR-016 and ADR-017 and leave the reviews as issues. I changed nothing in this repo — read-only feedback for the maintainer. Refs are to docs/ADRs/017_facts_across_a_private_boundary.md at fab6456, and to platform facts I hold from the consumer side.
Verdict: strong accept
This is the right decision and unusually well-argued. It correctly identifies the invisible failure as the one most deserving an automatic check (§1: upload succeeds, is paid for, consumer returns empty, nothing errors), and it resolves the credential-vs-declaration question at the level of the category, not today's instance (§4: 15/33 repos private; "there will be one or more private APIs at any time"). Two things stand out as rare: the copy-vs-authority distinction (§5, "But you rejected copying" — a copy that is also the thing you check against is the failure; a copy checked against a declared authority is just a value with a source) is genuinely subtle and exactly right; and §8 states plainly what it does not verify and accepts the third-party blind spot with a named owner rather than papering over it. The findings below are about sequencing and precision, not direction.
Findings
F1 — Appendix B step 1 has a hidden upstream dependency for the CRAF'd partner (medium)
Everything is blocked on step 1 — "declare the label for each partner in the coordinate registry" (views-appwrite#75). §2 already makes the honest admission that consumer-ownership is cited for FAO (ADR-013 §4.1a) but only assumed for CRAF'd. There's a second, sharper problem beyond ownership: CRAF'd's delivery label value does not exist yet to declare. On the consumer side, views-crafdapi's served schema / CONSUMER_DOCUMENT_NAME is still an open, blocked data-contract decision (the crafdapi epic's S8, needs-decision), because CRAF'd serves a different dataset whose targets/columns/entity model aren't settled. So the crafd half of step 1 can't complete as "one registry row" — it presupposes a decision nobody has made. Suggest: Appendix B note that step 1's crafd half is blocked on the CRAF'd data-contract (crafdapi S8), so views-appwrite#75 doesn't stall mid-edit waiting on a value that isn't decided, and so the FAO half (which is fully specified — un_fao) can land independently and unblock the FAO path first.
F2 — both sides verify "against the declaration," but nothing pins them to the same edition (medium)
§5 has the producer (here) and the consumer (faoapi, §8 / Appendix B step 3) each check their copy "against the same declaration." The registry is versioned with an amendment log (§6) — which means it has editions. If the two sides read the registry at different editions, both checks can pass while the effective label still mismatches across the edition boundary. The label is presumably immutable across editions, so this may be a non-issue — but that's an unstated assumption carrying a silent-failure mode, and §8 names only one residual path (the consumer changing its filter), not this one (edition skew between the two self-checks). Suggest: either state explicitly that the check pins the registry edition both sides agree on, or record why edition-skew is a non-issue (e.g., "the label is contract-immutable; a change is a new edition both sides re-pin to"). Given the ADR's care elsewhere, the assumption deserves a sentence.
F3 — §5.3's "because this repository is public" is true but load-bearing on the wrong fact (low)
§5 item 3 / §8: the consumer's self-check "needs no access to us either — this repository is public." But the consumer's check reads the registry (public), not this repository — it never reads views-postprocessing at all. So "this repository is public" is irrelevant to why the consumer's check is free; the fact that actually carries it is the registry is public. Minor, but this ADR prizes precise reasoning, and the imprecision slightly obscures the real (elegant) symmetry: neither side reads the other; both read a public third place. Tightening it makes §5's central rule land cleaner.
F4 — the highest-value guard stays manual for an unbounded, externally-blocked window (low / observation)
§1 calls the label mismatch "the failure mode that most deserves an automatic check," yet §5 + Appendix B leave it manual-in-CI until step 1 lands — which, per F1, for CRAF'd is blocked-on-a-blocked-decision, i.e. unbounded. The ADR is admirably honest about this ("the honest description of where we are"), but the interim state is exactly the one the whole of ADR-016 was written to end: a check that runs only when someone happens to run it. Suggest (optional): an interim tripwire that fails CI if the maintainer-machine check is stale/skipped (e.g., a dated assertion that must be refreshed), so the gap stays loud rather than reverting to habit while #75 is pending — the same "a check nobody watched fail is decoration" doctrine ADR-014 §2 applies to real guards.
Net
Accept as-is. F1 is the one I'd act on first — it's a real cross-repo sequencing trap (the FAO path is ready to declare now; the CRAF'd path is not, and bundling them in one #75 edit risks stalling the ready half behind the blocked one). F2 is a one-sentence assumption to make explicit; F3/F4 are precision/optional. Consumer-side owner note: Appendix B step 3 (views-faoapi#379) is mine to pick up when the registry declaration lands — I'll wire faoapi's served-label self-check against the registry rather than let §8's other half sit as a permanent blind spot for the FAO (self-operated) case.
External review, filed by request. I'm the agent working the
views-faoapi/views-crafdapi(consumer) side of this seam; Simon asked me to review ADR-016 and ADR-017 and leave the reviews as issues. I changed nothing in this repo — read-only feedback for the maintainer. Refs are todocs/ADRs/017_facts_across_a_private_boundary.mdatfab6456, and to platform facts I hold from the consumer side.Verdict: strong accept
This is the right decision and unusually well-argued. It correctly identifies the invisible failure as the one most deserving an automatic check (§1: upload succeeds, is paid for, consumer returns empty, nothing errors), and it resolves the credential-vs-declaration question at the level of the category, not today's instance (§4: 15/33 repos private; "there will be one or more private APIs at any time"). Two things stand out as rare: the copy-vs-authority distinction (§5, "But you rejected copying" — a copy that is also the thing you check against is the failure; a copy checked against a declared authority is just a value with a source) is genuinely subtle and exactly right; and §8 states plainly what it does not verify and accepts the third-party blind spot with a named owner rather than papering over it. The findings below are about sequencing and precision, not direction.
Findings
F1 — Appendix B step 1 has a hidden upstream dependency for the CRAF'd partner (medium)
Everything is blocked on step 1 — "declare the label for each partner in the coordinate registry" (views-appwrite#75). §2 already makes the honest admission that consumer-ownership is cited for FAO (ADR-013 §4.1a) but only assumed for CRAF'd. There's a second, sharper problem beyond ownership: CRAF'd's delivery label value does not exist yet to declare. On the consumer side,
views-crafdapi's served schema /CONSUMER_DOCUMENT_NAMEis still an open, blocked data-contract decision (the crafdapi epic's S8,needs-decision), because CRAF'd serves a different dataset whose targets/columns/entity model aren't settled. So the crafd half of step 1 can't complete as "one registry row" — it presupposes a decision nobody has made. Suggest: Appendix B note that step 1's crafd half is blocked on the CRAF'd data-contract (crafdapi S8), so views-appwrite#75 doesn't stall mid-edit waiting on a value that isn't decided, and so the FAO half (which is fully specified —un_fao) can land independently and unblock the FAO path first.F2 — both sides verify "against the declaration," but nothing pins them to the same edition (medium)
§5 has the producer (here) and the consumer (faoapi, §8 / Appendix B step 3) each check their copy "against the same declaration." The registry is versioned with an amendment log (§6) — which means it has editions. If the two sides read the registry at different editions, both checks can pass while the effective label still mismatches across the edition boundary. The label is presumably immutable across editions, so this may be a non-issue — but that's an unstated assumption carrying a silent-failure mode, and §8 names only one residual path (the consumer changing its filter), not this one (edition skew between the two self-checks). Suggest: either state explicitly that the check pins the registry edition both sides agree on, or record why edition-skew is a non-issue (e.g., "the label is contract-immutable; a change is a new edition both sides re-pin to"). Given the ADR's care elsewhere, the assumption deserves a sentence.
F3 — §5.3's "because this repository is public" is true but load-bearing on the wrong fact (low)
§5 item 3 / §8: the consumer's self-check "needs no access to us either — this repository is public." But the consumer's check reads the registry (public), not this repository — it never reads
views-postprocessingat all. So "this repository is public" is irrelevant to why the consumer's check is free; the fact that actually carries it is the registry is public. Minor, but this ADR prizes precise reasoning, and the imprecision slightly obscures the real (elegant) symmetry: neither side reads the other; both read a public third place. Tightening it makes §5's central rule land cleaner.F4 — the highest-value guard stays manual for an unbounded, externally-blocked window (low / observation)
§1 calls the label mismatch "the failure mode that most deserves an automatic check," yet §5 + Appendix B leave it manual-in-CI until step 1 lands — which, per F1, for CRAF'd is blocked-on-a-blocked-decision, i.e. unbounded. The ADR is admirably honest about this ("the honest description of where we are"), but the interim state is exactly the one the whole of ADR-016 was written to end: a check that runs only when someone happens to run it. Suggest (optional): an interim tripwire that fails CI if the maintainer-machine check is stale/skipped (e.g., a dated assertion that must be refreshed), so the gap stays loud rather than reverting to habit while #75 is pending — the same "a check nobody watched fail is decoration" doctrine ADR-014 §2 applies to real guards.
Net
Accept as-is. F1 is the one I'd act on first — it's a real cross-repo sequencing trap (the FAO path is ready to declare now; the CRAF'd path is not, and bundling them in one #75 edit risks stalling the ready half behind the blocked one). F2 is a one-sentence assumption to make explicit; F3/F4 are precision/optional. Consumer-side owner note: Appendix B step 3 (
views-faoapi#379) is mine to pick up when the registry declaration lands — I'll wire faoapi's served-label self-check against the registry rather than let §8's other half sit as a permanent blind spot for the FAO (self-operated) case.