feat(react)!: cascade layer, read-only mode, returnTo, and observe requirements (#97)
## Summary
Four things the Samva dashboard lane (#98) hit while adopting
`@domainkit/react`, plus the React
half of core's observe change.
## The stylesheet ships in a cascade layer — breaking
Part selectors were unlayered, so `[data-domainkit-part="domain-flow"]`
outranked a host's
`@layer utilities` and Samva laid parts out through the `style` prop.
Every rule now sits in
`@layer domainkit`, which puts the whole stylesheet below any unlayered
host rule.
**A host that relied on the package winning must now opt in**, by
ordering a layer of its own below
it:
```css
@layer domainkit, app;
```
An artifact test asserts the built stylesheet carries nothing outside
the layer, and a Playwright
case proves a host utility class beats a part.
## The member view
```tsx
<DomainKit.Root transport={transport} readOnly>
<Domain.Flow domain="app.example.com" requirements={requirements} />
</DomainKit.Root>
```
Status, records, and evidence render; connect, detach, disconnect,
review, approve, decline, and
cleanup do not. `Domain.Flow` takes the same flag for one domain among
several, and `useReadOnly()`
tells a host's own part which mode it is in.
Capability gating is the other half and is unchanged: a group the
transport never declares still
never renders. `readOnly` covers the authorization a transport cannot
express — a member who reaches
the same routes and would get a 403 from any write.
Observation stays available, because checking DNS reads the world rather
than changing the domain. A
host whose `Identity.authorize` denies `observe` to members passes
`slots={{ verification: () => null }}`.
## The interactive connect comes back
`Connect.useController`, `Connect.Flow`, and `Domain.Flow` take
`returnTo`, defaulting to the page
the customer is on and read when they connect rather than when the flow
renders. `null` sends none
and leaves the server's `defaultReturnTo` in charge; a per-call
`ConnectInput.returnTo` still wins.
## Verification no longer waits for an attachment
`Verify.useController` takes `requirements` and `Domain.Flow` passes its
own, so core's new
`observe(domain, { requirements })` verifies a domain with nothing
attached instead of failing
`InvalidInput` on the missing receipt. The set is keyed by content, so
an inline array does not send
the mount effect observing in a loop.
## Screenshots
| Read-only | Host utility beats a part |
| --- | --- |
| 
| 
|
## Tests
- 39 unit cases, 5 artifact cases, 10 Playwright cases.
- Each behaviour has a check that fails without it: the layer (artifact
and browser), `returnTo`
(default, explicit, and opted out), read-only (root, per flow, and off),
and observe requirements
(argument list, and no re-observe on an inline array).
`bun run --filter @domainkit/react release:check` and the root
`release:check` are green. S
Saatvik Arya committed
22b0c5958aad7eac218e2680b3e4982f2e1f9367
Parent: af128b0
Committed by GitHub <noreply@github.com>
on 9/3/2026, 8:36:30 PM