SIGN IN SIGN UP

feat(core): carry observe requirements over the wire (#96)

## Summary

Issue 102. `Verify.observe({ domain, requirements? })` already observed
supplied requirements for a domain with no attachment, but the
`verification.observe` route and `Transport.Interface` carried only
`domain`, so a host whose customers apply records by hand (most Samva
domains) could not reach that path from a UI. This carries the field
over the wire, additively.

## Field shape

Route `POST /domains/:domain/observations`, JSON body
`Server.ObservePayload`:

```ts
{ requirements?: ReadonlyArray<DnsRecord.Model> }   // encoded records, e.g. { _tag: "TXT", name, ttl: null, policy: "append", value }
```

Transport:

```ts
Transport.VerificationGroup.observe: (
  domain: string,
  options?: { readonly requirements?: ReadonlyArray<DnsRecord.Model> },
) => Fx<Readiness>
```

`observe(domain)` keeps working; the fetch transport always sends a JSON
body (`{}` when no requirements). The React controller plumbing for
`options.requirements` is the React lane's follow-up.

## Precedence when both exist

Supplied `requirements` win; otherwise the attachment's latest
provisioning receipt is observed; a domain with neither fails
`InvalidInput`. I kept this over "the attachment's plan wins and
supplied requirements are rejected" because an attached domain without a
provisioning receipt already tells the host to pass requirements, and a
host verifying a hand-applied record on an attached domain (a TXT the
plan never wrote) needs the same path. The docstring on
`Verify.Interface.observe` and ADR 0005 state the rule.

## Proof

- `tests/server/httpapi.test.ts`: `POST
/domains/nobody.example.com/observations` with a TXT requirement answers
200 with `attachmentId: null` and `PublicDns` evidence only; the same
route with `{}` on an unattached domain answers 400; the OpenAPI
document declares the request body.
- `tests/client/transport.test.ts`:
`verification.observe("nobody.example.com", { requirements })` through
`Transport.fromFetch`.
- `tests/testing/host.test.ts`: `Testing.transport()` observes
hand-applied records and records the call as `{ method:
"verification.observe", input: [domain, { requirements }] }` (the
recorder now keeps every argument when a method takes more than one).
- `tests/verify/observe.test.ts` already covers the core path for a
domain with no attachment.

## Validation

- Core gate (oxfmt, lint, typecheck, 134 tests), `bun run --filter
domainkit build`
- Root `typecheck` (react and capsuledb against the rebuilt core)
- `bun run --filter domainkit release:check` (10 artifact tests) and
root `release:check`
- Live provider tests are user-owned and were not run

https://claude.ai/code/session_017P54ng7iisz1dsk18u1w1x
S
Saatvik Arya committed
10b8a34de249225e4ff048d1adf3f7961e11f248
Parent: 6c6718b
Committed by GitHub <noreply@github.com> on 9/3/2026, 8:09:01 PM