oficina / suite Public

Clone
git clone https://amadan.net/oficina/suite

Plain git — no account needed to clone.

Download

Download this file

1# GPT-6 review of the contract module
2
3**Verdict: request changes.** Reviewer: GPT-6 via Codex, 2026-09-05, at
4`1cc739e`, against the doctrine at revision 4.
5
6The reviewer could not write this file itself — a `writing-pipeline` skill
7on this machine requires a drafting API that was unreachable, and it
8correctly stopped rather than substituting itself for the missing tool.
9The findings below are transcribed from its session log without
10editorialising. Where a claim is marked reproduced or executed, that is the
11reviewer's own word for work it did.
12
13**Verification it performed.** go1.26.5 on Linux; baseline `go test ./...`
14passing; probes under `/tmp/codex-module-review`, using `net.Pipe` to
15capture an HTTP request rather than a network; and six mutated copies of
16the module. The repository's own code was never modified by the review.
17
18**Six deliberate regressions survived the full test suite.** That is the
19headline, and it matters more than any single finding: the module's tests
20were weaker than the commit message claimed.
21
22## What has been done about it
23
24Fixed, each with a test that fails without the fix: **1** (the `Host`
25override), **2** (duplicate JSON keys), **3** (S3 bodies compared, and a
26never-existent id as the refusal baseline), **5** (three S2 questions — the
27asker, the asker one revision behind, and a person with no team standing),
28**8** (`DecodeS1` rejects nulls, missing fields, trailing content and
29duplicate keys), **9** (RFC 1123 label validation), **10** (gate 4's
30redirect half runs against a real 302 through a counting dialer, using the
31fixture case that was never read), **11**, **12**, **13** and **14** (the
32tests that could not fail).
33
34`mutations.py` re-runs all nine regressions, including the three the review
35did not name. All nine are caught.
36
37**Still open, and honestly so:**
38
39- **Finding 4.** The harness asserts the feed parses, not what is in it. An
40 always-empty feed still passes, and the reference server still announces
41 every fixture id as `gone`, which exposes the ids of items that were
42 never team-visible.
43- **Finding 6.** The fixture is single-pass and captures final states only.
44 There is no ingest-then-downgrade transition, so a server caching a
45 positive answer across requests passes.
46- **Finding 7.** The harness sends no Authorization, Origin or JSON
47 Content-Type, and never uses `fixture.Team`. A server with correct bearer
48 auth fails every check; a server with no auth at all passes.
49
50Finding 7 in particular wants a fixture that can carry consumer credentials,
51which is a change to the fixture's shape rather than a patch. Left for the
52first app that adopts the module, per §12 step 3 — the second implementation
53is what corrects the fixtures.
54
55---
56
57## P1
58
59**1. The team guard reads `req.URL.Hostname()` and ignores `req.Host`.**
60`transport.go:48-53`. A POST whose URL is `acme.docs.oficina.works` but
61whose `req.Host` is `other.docs.oficina.works` dials our own team and then
62sends `Host: other.docs.oficina.works` with the whole body and the consumer
63token. Reproduced in an in-memory probe. A shared platform router that
64routes on the HTTP Host could deliver it to the other team; that routing
65was not tested. This is an alternate authority field and a
66mis-provisioning hole, not a claim about hostile code, which §4.1 already
67excludes. *Correction:* reject any non-empty `Host` override whose
68canonical authority differs from the URL's.
69
70**2. Duplicate JSON keys defeat the duplicate-row rule.** `s2.go:51-66`.
71`encoding/json` collapses duplicate object keys before the pair-duplicate
72check ever runs, so
73`{"item_id":"doc-1","revision":7,"result":"NOT_VISIBLE","result":"VISIBLE"}`
74decodes as `VISIBLE`. So does a second key spelled `RESULT`, and so does
75repeating the whole `results` array. A row carrying `revision:6,revision:7`
76reassigns the answer onto revision 7. All reproduced. *Correction:*
77validate member uniqueness at envelope and row level, aliases included.
78
79**3. The harness checks S3 status and never the body.**
80`conformance/conformance.go:68-80`. A handler that returns the required 404
81for private and granted rows while including item-specific secret bodies
82passes all 19 checks, as does one that returns the wrong item's bytes with
83a 200. No never-existent id is ever requested. `DecodeS3` discarding a 404
84body does not protect a caller reading the raw response. *Correction:*
85golden bodies for success and a canonical refusal body; compare raw bytes;
86request a never-existent id.
87
88**4. The harness accepts any feed that parses.**
89`conformance/conformance.go:120-126`. An always-empty feed passes, and so
90does a feed carrying a live row for an item that was never public. Worse,
91the reference server emits every fixture id — including the private, guest
92and link-only ones — as `gone` rows, exposing their ids, revisions and
93timestamps, and the harness calls that correct. *Correction:* golden
94initial and incremental feeds with per-consumer history; assert row
95membership and values; departures only for previously eligible items.
96
97**5. S2 is exercised with one asker, one revision, one request.**
98`conformance/conformance.go:87-114`. Every expected answer reduces to
99`rung == team`, and the reference server ignores the asker and the revision
100entirely — returning `VISIBLE` for any asker and any revision of a team
101item — and still passes. *Correction:* matched and mismatched subject
102kinds, an unknown kind, two people with different access, revisions
103before/equal/after current, and all four outcomes.
104
105## P2
106
107**6. The custody fixture uses a distinct id per case**, where gate 3 asks
108for the same id in different states, and captures only final states with no
109grant, member or history setup. `doc-was-team` and `doc-link-added-late`
110perform no ingest, downgrade or link change; the late-link case is
111private-only with no team-visible control. A server caching positive
112answers across requests passes this single-pass setup and leaks after a
113downgrade.
114
115**7. The harness sends no Authorization, Origin or JSON Content-Type**, and
116never uses `fixture.Team`. A receiver with correct bearer auth answers 401
117and fails all 19 checks; enforcing JSON Content-Type gives 415 on S2. So a
118server with no auth at all passes, which encourages bypassing the
119middleware to satisfy the gate.
120
121**8. `DecodeS1` decodes only the first JSON value and validates nothing.**
122It accepts `null`, `{}`, a row of `{}`, null `gone`/`touched_at`, and
123trailing garbage after a valid page — including trailing JSON containing a
124title. Duplicate `gone:true,gone:false` leaves `false`. A null or missing
125field yields a live zero-value row, so an advanced cursor can commit an
126invalid page and a malformed departure can lose a tombstone.
127
128**9. The host check counts dots and never validates a label.**
129`transport.go:67-90`. `CheckSiblingHost("acme", …)` admits
130`acme..oficina.works`, `acme.-docs.oficina.works`, `acme.docs_.oficina.works`
131and `acme.docs。evil.oficina.works` with an ideographic full stop, whose
132label count can change under IDNA normalisation. No valid same-team ASCII
133host is wrongly refused. *Correction:* validate non-empty bounded ASCII DNS
134labels; reject or canonicalise Unicode before counting.
135
136**10. Gate 4 is not a shared executable gate.** `fixtures_test.go` ignores
137the fixture's `redirect` field entirely; `transport_test.go:81-93` calls
138`CheckRedirect` directly with no 3xx and no connection counting; and
139`conformance.Check` takes only an `http.Handler`, so a consuming app has no
140way to run the client-side gate at all. An app using a redirect-following
141unguarded client passes the published `Run`. This is a coverage and API
142finding, not a claim that redirects are currently followed.
143
144**11. The non-2xx test asserts nothing when the decoder returns nothing.**
145`s2_test.go:55-71` ranges over the result without a length check, so
146mutating that branch to `return nil` makes the test perform zero
147assertions and the suite pass. The test cannot fail on the one path its
148name describes. *Executed.*
149
150**12. The S2 tests use two ids, one revision each, and never a `STALE`.**
151Mutating the decoder to ignore `Revision` in both map insertion and lookup
152passes the full suite; so does deleting `STALE` from the `known()` switch.
153The implementation is correct; the tests cannot tell. *Both executed.*
154
155**13. The cap test derives both sizes from `MaxS2Pairs`**, so it checks
156self-consistency rather than the doctrine's 256. Changing the constant to
157512 passes the entire suite. *Executed.*
158
159## P3
160
161**14. The 403 test never asserts `errors.Is(err, ErrContractBreach)`.**
162Mutating the 403 branch to a generic error passes, losing the breach/outage
163distinction the file promises.
164
165---
166
167## Gate verdicts
168
169| Gate | Verdict |
170|---|---|
171| 1. Fixture conformance | Incomplete — bodies, feed contents and auth unchecked |
172| 2. S2 total decoder | Incomplete — ambiguity, wire shape, and three surviving mutations |
173| 3. Custody | A static subset — no wire equality, no transitions |
174| 4. No cross-team dial | Partial unit coverage, not a shared executable gate |
175