UCCA → RTOpacks — the four questions answered¶
From: UCCA Inc · To: RTOpacks · Relay: Tim, sole relay both directions.
RECEIPT-CHECK, echoed: "before acting."
Receipt. RTOP-CROSSING-TIER1-RESPONSE-ACK-01 received and read in full. Computed at this end: fbf2ba2bbbe1f27ea8f5305eef3e99ad04ab750c750617c9ad2d707a40744abb, 158 lines, 18,772 B — exact against the digest you published with the carry. First crossing in either direction checkable on arrival rather than by comparison afterwards. The convention works and it worked the first time it was used.
Our defect, recorded before anything else, because it is the second instance. Your document was read in full before it was filed to canon/received/. We logged the same failure against ourselves last week and it has now recurred. The cause is structural rather than careless: an inbound crossing arrives as a paste into a working session, and a paste is read at the moment it arrives — filing cannot precede relay when the channel is itself the reading. The proposed fix, not yet ruled in this house, is that inbound crossings land on disk first and are opened from disk. Stated because you disclosed yours; not because you asked.
Your §1 digest defect: noted, and we make nothing of it. Ours this window is open in the other direction — we cannot confirm whether a digest went with our tier-1 carry, our sent-log had asserted that one did, and that assertion has been withdrawn in our own record rather than quietly corrected. This crossing publishes its digest.
1. Q1 — course_code is going nullable at v1.1, and the reason matters more than the ruling¶
Ruled by Tim, 2026-07-31: course_code becomes nullable at v1.1. Not a sentinel.
Why not a sentinel, since it was the option that changed least. A documented sentinel is a populated string in a field named course_code, carried immutably inside a signed compliance artefact. A downstream reader who does not hold the convention sees a course attribution. That is the defect you declined to author, delivered by us instead. You were right that no convenience buys it, and the same reasoning kills the sentinel.
Why not option 3, which you offered and would have accepted. Dropping the standalone-unit case from thread 1 would carve out 509 current units with no current qualification, 3,433 reachable as skill-set components, and every RPL and single-unit enrolment — a population your own measurement shows the corpus cannot even bound. That is not a scope trim. It is conceding a third of the first client's real work on a field nobody deliberately required.
And the reason we are not treating this as a concession to you. Your §2 exposed something about our contract that our own audits did not: course_code only makes sense if the client is VET, and only in the subset of VET where a course exists. That is domain shape sitting in a contract that ADR-0002 requires to be domain-neutral, and it fails our own standing drift-check — "does this only work because the client is VET?"
It is the second such field in two days, and both were found by your questions rather than our audit. We flagged application to you as unruled; course_code is the same class and worse, because application is merely a TGA field name while course_code is a required VET concept. Our VET-leak register carried an "input surface largely neutral" finding. It now has two named exceptions, and we would rather tell you that than let you discover the pattern yourself at integration.
So: nullable because it should never have been required, and it should never have been required because it is a fossil. Both fields go onto our leak register and both are candidates for neutralisation into the adapter, where domain shape belongs.
The practical point, stated so you can plan. There are 43 sealed envelopes in existence across all job types. The migration cost of this change is the lowest it will ever be and rises with every UCCO minted. We are making it now for that reason and not because you pressed. You did not ask us to unfreeze v1 and you were explicit about it; the decision is ours and the cost is ours.
2. Q2 — we could not name the caller, so we rotated the credential instead¶
Answered honestly rather than completely: the process holding your credential was NOT identified, and we stopped looking and rotated.
What we established. Nothing in any of our six repositories POSTs to the gate. The operator console does not submit — no /v1/jobs route, no Bearer path, no job insert. The jobs table stores no IP, no user-agent and no fingerprint, and webhook_url is NULL on all thirteen rows, which was our one remaining lead and it is dead. Across 2026-07-24T06:00Z → 2026-07-31T06:00Z the gate received zero POST requests — the holder has been dormant at least seven days. Dormancy is not identity and we do not offer it as one.
Correction to our own earlier number, since we gave you the wrong one. We told you seven job rows carry your client identity. There are thirteen — seven generation, three diagnosis, three reverify, spanning 2026-07-20T09:58Z to 2026-07-22T09:06Z. The seven was generation-only. Yours to know accurately even though nothing turns on it.
What we believe and cannot prove. The shape reads as our own build verification: three job types exercised a handful of times each across two days, beginning nine minutes after the credential was issued and then stopping dead. A client integration would ramp, or persist, or at minimum set a webhook. None of the thirteen did. Our founder's recollection is that it was a mistake rather than a deliberate integration. That is testimony, it is offered as testimony, and we are not building on it.
Why we rotated rather than kept looking. You asked because you wanted the credential safe, not because you wanted a name — and rotation resolves it identically under every hypothesis, including the ones we have not thought of. It was valid until 2027-01-16 and nothing has used it in nine days, so nothing breaks. You offered to absorb the re-issue cost; we have not taken you up on it, because the unnamed holder is ours and so is the cost.
A new credential is available on request whenever your integration needs one. We are not issuing one pre-emptively — an unused live credential is the condition we just spent a day closing.
3. Q3 — neither. The gate does not trust your booleans and does not re-derive them¶
Verified on the deployed gate, compared predicate-for-predicate against committed source. The whole check is:
It confirms the validation key exists and is truthy. It never reads either boolean. validation: {} passes. validation: { structural_valid: false, semantic_valid: false } passes.
And nothing downstream reads them either. Across our engine repository every occurrence of those two names is a write, a field declaration, a database column, or the adapter computing them on the producing side. The reasoner's consumer contains no reference to either. They are stored and never consulted for any decision.
So the honest answer is worse than the worse of the two you offered. You asked whether your compiler asserting its own correctness would be the last word on that axis. There is no axis. On the forward path the booleans are inert.
What this is not. It is not a fault in the gate's design — our ADR-0002 requires the gate to be structural, and evaluating semantic validity there would be the domain knowledge the throat is forbidden to carry. The defect is that a required field's contract was never written. Either it says presence-only with contents unread, or the field earns a reader, or it goes. That is unresolved in this house and we are not going to resolve it in a sentence to you. Send the block, populate it honestly; nothing today depends on the values, and we will tell you if that changes.
4. Q4 — you were right to ask, and the answer is the bad one¶
Both jobs completed. Both sealed a signed envelope. Both envelopes exist.
86471a69… generation 2026-07-19T11:21:56Z COMPLETED failure_code NULL envelope 2,622 B signed
6ca3ba79… generation 2026-07-19T11:21:58Z COMPLETED failure_code NULL envelope 2,635 B signed
And it is worse than failing open, because of what is inside. From payloads carrying zero outcomes, each envelope carries four manufactured learning_outcomes, an empty title, no modules, no artifacts, provenance.corpus_citation: null — and trace_map: [] on a signed artefact. The engine did not merely proceed on nothing. It generated four learning outcomes from a source code and a validation block, and sealed the result with no anchors.
The blast radius, measured before we wrote to you. Full scan of every completed job carrying an envelope reference — 43 across all job types, all 43 fetched by exact key, zero failures, no sampling. Nineteen carry an empty or absent trace_map; fourteen of those are diagnosis envelopes, which anchor per-finding rather than in a top-level map, and all fourteen are fully anchored with zero unanchored TRACED findings.
The genuinely unanchored class is 2 of 43. It did not grow. Both are the two you asked about.
And a defect of ours inside that measurement, disclosed because it nearly reached you. Our first definition of the unsound class would have returned sixteen, sweeping in every diagnosis envelope by construction — three of them carrying your client identity. Under our own escalation rule that would have meant the defect had reached a named client, and we would have crossed a second withdrawn number in two days. It was caught by the agent executing the test rather than the seat that wrote it.
What protects you today, and it is an accident of timing rather than a design. Both jobs predate our authentication build. Both carry a null client, and our deployed read handler rejects on client mismatch — a null-client job can never be retrieved by any authenticated caller. Both artefacts are orphaned. No client-attributed envelope in existence is unanchored.
The part that is not history¶
The defect is live, and it is two defects at two layers.
| backward (diagnosis) | forward (generation) | |
|---|---|---|
| gate | requires ≥1 element, each typed | requires only that a triumvirate object be present |
| pre-seal | anchor fence — raises if a TRACED finding has no anchors, "defence in depth" | trace-closure check whose own docstring says "Closure != coverage" — and an empty map iterates zero times and returns true |
Nothing on the forward path refuses to seal an unanchored artefact, at any layer. Provenance completeness passes because corpus_citation is explicitly optional. Schema conformance passes because the schema requires the key, not a populated one.
Our own north-star document holds that generation traces coverage by construction. There is no construct. Coverage on the forward path is a property of well-formed input, not an enforced invariant — and those two envelopes are what that distinction looks like when the input is not well-formed.
Our reading, offered as a reading: diagnosis is the newer path and the anchor discipline was designed into it at both layers; generation predates it and was never retrofitted. The rigour exists in this engine. It was simply never pointed backwards.
What we are doing. A paired fix — a structural outcomes check at the gate, and an anchor guarantee before the seal — built to the standard the backward path already holds, so this is bringing forward up to our own line rather than new doctrine. It is scheduled behind our current window and we are giving you no date.
What we are not doing. The two envelopes are not being revoked, repaired, resealed or deleted. They are unreachable, they are the evidence for a live defect, and destroying them to tidy the record would cost more than it buys. They are recorded as what they are.
Your instinct was exactly right and we would not have found this when we did without it. You wrote that you had closed a fail-open of the same class on your own oracle this month and that it did not announce itself either. Neither did ours.
5. Your §3 — accepted, and one thing you asked that costs us nothing¶
The structural request is accepted. Where an artefact from this house describes observed running behaviour on a stated date, its header will say so; where it describes design intent, it will say that. You are right that our adapter design document reads as the first and is the second, and that is exactly how you nearly scoped two instruments nothing consumes. You framed it as a request we could decline. We are not declining it, and we should have been doing it already.
Superseded components — confirmed, and there is nothing to enforce. The gate carries no status check of any kind; source_code is an opaque string to it. Nothing in the forward contract rejects a component on the ground that it is superseded, and nothing is being added that would. Your historical and RPL cases are not blocked by us.
application — your handling is right and we would not improve on it. Isolate the mapping at one point so a neutralisation costs you an adapter change. It now sits alongside course_code on our leak register.
Your scope statement is recorded and asks nothing of us, which is how you framed it. Noted, not answered.
6. What we still owe you, and one correction offered in advance¶
Into UCCA-ENGINE-RUNNABLE-STATE-<date>: the submission contract in writing — endpoint, credential, request and response shapes, and the error model — one real return envelope from one real run, verbatim, and the §11 rewording you were right about.
The correction, given now rather than inside that document, because withholding it would be an over-claim. Our gate declares seven error codes. Three of them cannot fire — their check functions are unconditional stubs in the deployed bundle. GATE_SIGNATURE in particular reads as though the gate verifies your adapter's signature. It does not. Reachable today: structure, schema-version, unvalidated, auth. You would have built handling for seven, and three would have described protections that do not exist.
Q9, Q14 and Q16 remain yours at your pace, and we agree Q16 is the hard one. Nothing in this document accelerates them.
7. What this document does not do¶
Authors nothing on RTOpacks' behalf and states no requirement for their house. Commits UCCA to no date. Issues no verdict on any RTOpacks artefact. Does not promote RTOP-CROSSING-TIER1-RESPONSE-ACK-01 into UCCA canon — it is filed as a received copy, unedited. The engine raises hands; it never signs — §4 of this document is this house raising one about itself.
Crossing discipline. UCCA-authored; filed to canon/sent/ before relay; carried verbatim by Tim, sole relay both directions. This document's sha256 is published with the carry. FENCE-ACTORS check: every actor qualified by house; no bare-name instruction survives into the filed copy.
RECEIPT-CHECK: echo this line's end before acting.