Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .github/workflows/run_pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,6 @@ jobs:
path: _siblings/views-appwrite
fetch-depth: 0

- name: Checkout views-crafdapi (sibling)
uses: actions/checkout@v3
with:
repository: views-platform/views-crafdapi
ref: main
path: _siblings/views-crafdapi
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
with:
Expand All @@ -97,7 +89,6 @@ jobs:
- name: Run tests
env:
VIEWS_APPWRITE: ${{ github.workspace }}/_siblings/views-appwrite
VIEWS_CRAFDAPI: ${{ github.workspace }}/_siblings/views-crafdapi
run: |
set -e
poetry run pytest tests/
24 changes: 15 additions & 9 deletions docs/ADRs/016_ci_read_access_to_private_siblings.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Who is who, once and in one table:
| repository | public? | fetched by CI? | why not, if not |
|---|---|---|---|
| **views-appwrite** | yes | **yes** | — carries the registry drift checks |
| **views-crafdapi** | yes | **yes**, temporarily | — retires when views-crafdapi#53 lands, not before (ADR-017 §5 is per partner) |
| **views-crafdapi** | yes | **no**, since 2026-08-12 | it was fetched for one test; that check read the consumer's source, broke twice in a day when both consumers improved theirs, and was deleted rather than repaired (ADR-017 §7 and its §5 erratum) |
| **views-datafactory** | yes | no | its checks need raw data that is not in its git repository; fetching it turns an honest skip into a crash |
| **views-faoapi** | **no** | no | private — no amount of workflow configuration reaches it. That case is [ADR-017](017_facts_across_a_private_boundary.md) |

Expand Down Expand Up @@ -148,12 +148,14 @@ Each rule is a plain function, so each is also run against a deliberately broken
to prove it objects. A rule only ever tried against a correct file is a rule nobody has
watched fail.

**One of these downloads is temporary, and it is worth knowing which.** `views-crafdapi` is
fetched for exactly one test. [ADR-017](017_facts_across_a_private_boundary.md) §7 replaces
that test with one that reads a public declaration instead — at which point this download
buys nothing and goes. That has been decided and is not yet done; it waits on the
declaration landing in the registry. That is a decision this document cannot make on its own, which
is why it is recorded there and cross-referenced here.
**One of these downloads was temporary, and it is worth knowing what became of it.**
`views-crafdapi` was fetched for exactly one test — a check that read the consumer's own
source. [ADR-017](017_facts_across_a_private_boundary.md) §7 said this repository was never
entitled to depend on another's file layout, and on 11 and 12 August 2026 both consumers
proved it by refactoring a literal into a named constant and reddening this repository
twice in a day. The check was deleted rather than repaired, and the download went with it.
What that costs is register C-92: nothing here verifies that a consumer's query uses the
name it declares.

### §6 A repository CI expects but cannot find turns the build red

Expand Down Expand Up @@ -311,8 +313,12 @@ the record that owns it.
**Update 2026-08-11.** The declaration now exists (views-appwrite#75), views-faoapi
checks itself against it (their #379), and this repository's check reads the registry
rather than that repository's source. So the FAO half is no longer laptop-only, and no
credential was issued. What remains is CRAF'd's consumer-side check (views-crafdapi#53);
until it lands, that partner's source-read stays, and with it that partner's fetch.
credential was issued. CRAF'd's consumer-side check landed the next day (views-crafdapi#53, closed 2026-08-12).

**Amended 2026-08-12.** Both source-reads are now gone, and the crafd fetch with them —
but not because those gates opened. The reads broke twice in twenty-four hours, each time
because a consumer improved its own code, so the mechanism was abandoned rather than
sequenced out. ADR-017 §5 carries the erratum; the residual is C-92.

---

Expand Down
74 changes: 57 additions & 17 deletions docs/ADRs/017_facts_across_a_private_boundary.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,43 @@ machine for the private one. Slightly redundant for a while, and redundancy is t
price for not having a window where the only thing verifying a delivery label is our own
typing.

**Erratum, 2026-08-12. The sequence above was followed, and the check was still the wrong
mechanism. Both facts belong here, and an earlier draft of this erratum got the first one
backwards.**

Both partners' step 3 landed. views-faoapi#379 closed on 11 August (commit `8615574`);
views-crafdapi#53 at 12:15 on the 12th (commit `0c493ae`). So the constraint stated above was **satisfied**, not
bypassed — and the first version of this erratum claimed the opposite, that "neither
partner's step 3 is what removed them". That was false when written, six hours after the
second one landed. It is corrected here rather than quietly, because an ADR that repeals
its own rule on a false claim about another repository is §3's failure inside §5's text.

**What actually happened is more useful than what that draft said, and it is checked
rather than asserted.** In both repositories the commit that satisfied step 3 was *the
same commit* that broke our source-reading check — verified: `8615574` and `0c493ae` each
introduce the named constant and add that repository's registry-binding test: each consumer, while binding its served name to the registry, tidied
`APIPathManager("literal")` into `APIPathManager(CONSUMER_DOCUMENT_NAME)`. The improvement
and the breakage were one edit. Twice, a day apart.

That is the argument for removing the check, and it is **§7's argument, not §5's**: we were
never entitled to depend on another repository's file layout, and a mechanism that a
consumer breaks by improving itself will keep breaking. The ordering rule above did its
job; the thing it was ordering was not worth having.

So the ordering constraint is not repealed — it is **discharged**, and superseded for this
class by a plainer rule: **a check that reads another repository's source is not a check
this repository builds.** The residual window is now permanent rather than temporary,
registered as **C-92**, and what closes it is each consumer proving its query uses the name
it declares — asked for in views-faoapi#390 and views-crafdapi#55, because that is a fact
only the consumer can hold.

**One assumption worth stating rather than relying on.** The registry is versioned, so the
two sides could in principle read it at different editions and both pass while disagreeing.
That is not a live risk here because the label is contract-immutable — changing it is an
amendment, which produces a new edition both sides re-pin to, and our pin's reachability is
already checked. Recorded because an unstated assumption carrying a silent-failure mode is
what §1 is about. Today the check still reads the consumer's source
and still skips in CI. The order the three land in, and what is blocked on what, is
what §1 is about. *(Until 2026-08-12 the check also read the consumer's source and
skipped in CI; see the erratum above — that half is gone and its residual is C-92.)* The order the three land in, and what is blocked on what, is
Appendix B. Said here because a decision record that reads as a description of the code is
how this repository has repeatedly ended up believing work was done.

Expand Down Expand Up @@ -377,21 +407,31 @@ visibility can be inferred for future APIs.

Corrected: **retirement is per partner, and follows that partner's step 3.** For FAO
that is now met (views-faoapi#379 merged 2026-08-11), so the FAO source-read goes. For
CRAF'd it is not (views-crafdapi#53 open), so the crafd source-read stays — and with
it the crafd fetch, whose `note` in `tests/conftest.py` already records that it lives
or dies with that one check.
CRAF'd it was not yet, so the crafd source-read stayed — and with it the crafd fetch.

*(Superseded 2026-08-12. views-crafdapi#53 closed at 12:15 that day, and the crafd
source-read was deleted anyway — not because the gate opened, but because the mechanism
was wrong. Both fetch and check are gone; `tests/conftest.py`'s note records it. See the
§5 erratum.)*
3. **views-faoapi** — verify its own served label against the declaration; §8's other half.
Filed as views-faoapi#379, and the consumer-side maintainer has accepted it.

4. **views-crafdapi** — the same self-check for the other partner. **Not yet filed at the
time of writing, and that gap matters**: §7 retires the crafdapi fetch, so without this
leg the CRAF'd label would end up checked against a registry row that nobody checks
against CRAF'd's actual code — no verification against reality at all, which is worse
than the status quo. §7 argues the rule must apply uniformly; uniform application means
uniformly filing the third leg. Sequenced after that partner's data contract settles,
per step 1.

**Step 3 is a precondition for removing the old check**, though not for adding the new one
— see the sequencing note in §5. The order is safe to interrupt at any point: until step 3
lands for a partner, that partner's source-reading check stays, so no window exists in which
the label is verified only against our own typing.
4. **views-crafdapi** — the same self-check for the other partner. Landed as
views-crafdapi#53 (closed 2026-08-12), with the *query*-side ask filed the same day as
views-crafdapi#55 alongside views-faoapi#390.

The reasoning that made this leg necessary still stands: §7 retires the crafdapi fetch,
so without it the CRAF'd label would be checked against a registry row that nobody
checks against CRAF'd's actual code — no verification against reality at all, which is
worse than the status quo. §7 argues the rule must apply uniformly; uniform application
means uniformly filing the third leg.

**Step 3 was a precondition for removing the old check**, though never for adding the new
one — see the sequencing note in §5. The order was safe to interrupt at any point: until
step 3 landed for a partner, that partner's source-reading check stayed, so no window
existed in which the label was verified only against our own typing.

**That last sentence stopped being true on 2026-08-12, deliberately.** Both source reads
were deleted once the mechanism — not the ordering — was found wanting, so the window is
now permanent and carried as **C-92**. See the §5 erratum for why the constraint was
discharged rather than repealed.
Loading
Loading