# Nook acceptance

`rer verify` is the complete local command for the implemented evidence described below. It does not establish unimplemented target journeys. Push CI runs contracts,
unit tests, runtime journeys at both widths, and notifications in thirteen parallel
jobs with 15-minute limits. The guided installer, full README and realistic pilot fresh-clone
journeys at 1440 and 390 retain every assertion and run nightly, on release tags,
and manually. It covers real Workers and local D1: runtime suites use the emitted build,
while the README and pilot journeys use the ordinary rer development workflow:

- current sessions and conversation ACLs on every API, document and generated
  server function, including expired, revoked and missing sessions;
- exact retry identity, compare-and-swap edits, tombstones and complete replay;
- fixed DMs, owner-controlled channel membership and full-history disclosure;
- decisions with version history and commitments accepted only by the assignee;
- private file staging, binding, download and erasure;
- calm attention (follow, mute, quiet time, snooze, done) independent of unread
  and of accepted work;
- `tests/notify-journey.mjs` (C14 email): the emitted Worker with local D1,
  native email-link sign-in and a fake provider at the test harness's network edge,
  through public
  doors: email off until a member turns it on (with the keyboard, at 1440 and
  390), one email for a mention while away and for a commitment proposal,
  nothing for a routine follow or during quiet time, urgent requests held or
  let through by the recipient's choice, two mentions folded into one email
  with a count, cancellation after removal from the conversation, deletion of
  the message or deactivation, a refused send retried on schedule and shown as
  "email not delivered" to the sender and the owner before it succeeds once,
  a queued retry surviving a Worker restart, the no-session "turn these off"
  link, and no message text or file name in any email;
- immutable imported history; the supported Base portability v1 recovery is the
  explicit backup-only `rer import --legacy-v1 --input FILE --yes
  --acknowledge-unverified-metadata --output FILE` path. It checks the v1
  checksums, records that the archive's metadata is unverified, restores into an
  empty installation, and writes a fresh v2 archive. The legacy single-workspace
  document conversion and root SQLite/native archive procedures are separate
  offline recovery paths in `OPERATIONS.md`; this is not recovery from every
  earlier format;
- the rer command contract: setup, first-run `/setup`, key-gated local dev sign-in, preview,
  doctor, reset, export/import round trip, the guided installer, owner-account
  deploy against a fake Cloudflare account, and a fresh-clone README journey;
- normalized storage: an install from migrations 0001–0003 moving forward, 25 MiB R2 attachments and
  Durable Object fanout with replay from D1;
- two people in two sessions at 1440 and 390: own sends never unread, viewing
  clears unread, Attention Accept and Discuss, threads and URL state;
- day-one team surfaces at 1440 and 390: hosted invitation semantics at the fake
  provider edge, local teammate entry, guest scope, deactivation, channel browse and join, reactions, inline image preview,
  tab-title count and retirement of duplicate open-tab OS notifications;
- Slack export import on synthetic fixtures: review, resumable apply,
  imported history and search, guarded undo, and the wizard at 1440 and 390;
- `tests/pilot-journey.mjs`: a fresh local rer install/setup, two independent
  dev-authenticated browser sessions at 1440 and 390, local teammate entry, private
  conversation/file, reviewed realistic Slack history with supplied files and
  an explicit missing-file choice, a complete root/thread/file census, source
  reactions/mentions/edited markers, selected audiences and revocation, unchanged
  unread/attention/mail counts, populated safe/refused undo, and rer export/reset/
  import with identical reexport content;
- desktop (1440) and mobile (390) browser and keyboard journeys and the homepage.

The pilot uses a realistic synthetic fixture shaped from Slack’s documentation: 5,000 source messages over 15 months, 40 source directory entries and six channels (one empty), with threads, bot/app records, files, edits, reactions and administrative records. No real Slack export or Slack account was used. The fixture supports bounded local verification, with no Slack parity claim.

Private inline image evidence is split between `tests/team-image.test.mjs`, which accepts genuine PNG bytes and rejects active content, truncation and corruption, and `tests/team-browser.mjs`, which loads a private image preview through the actual Worker at both widths. `ImagePreview.tsx` fetches the ACL-checked PNG/JPEG endpoint and renders a revocable blob URL; downloads remain forced attachments. These checks do not establish virus scanning.

The separate docs site suite checks manifest coverage and rejects broken pages,
anchors and raw HTML. `docs/site.json` currently publishes 12 public guide
routes. An earlier local browser pass exercised the sidebar, table of contents
and pager at 1440/900/390; its axe check covered the docs home and the long
mobile guide with its menu open.

`node tests/part6.mjs --platform-root PATH` needs a checkout of the platform
repository, so it runs outside verify. It proves the schema-2 artifact, the
signed owner claim, owner/anonymous Lobby equality at 1440 and 390, editor
authority and compiled-source persistence against the emitted Worker. The old
installed-homepage editor, draft and visible-publication checks were retired
when installed `/` became the session-independent Lobby.

The core runtime browser journey uses the repository-pinned axe-core package to
check the conversation with channel/thread routing closed and open, plus the
native message and member erasure dialogs, at 1440 and 390. It fails on serious or
critical axe findings. This bounded check does not cover imported-author
erasure and is not a full accessibility audit or WCAG claim. Hosted operation
on a real Cloudflare account, live mail-provider delivery, capacity beyond local
measurement, integrations and real-team adoption remain unproven. Email has a
local journey with a fake provider at the network edge; C15 Web Push has the bounded local checks
below. Neither establishes delivery to a real inbox, browser or device. The
installable PWA is shipped, but offline operation is not supported: its service
worker caches no requests or private content. There is no native iOS/Android
push transport or paging guarantee. Local synthetic verification is not a
production, parity or adoption claim.


## C15 Web Push evidence boundary

`pnpm test:push` runs the emitted Worker, real local D1 and the real ChatHub alarm. One core public-route flow signs in, registers an owned subscription, opts in, sends a message, and independently verifies VAPID and decrypts the actual outbound RFC 8291 packet at the sole fake network edge. A new conversation then proves read-before-delivery cancellation without relying on folding. Focused public security coverage rejects missing sessions, cross-origin mutations, another account's subscription ownership, non-vendor endpoints, invalid keys and unsupported transports, and checks that responses expose no endpoint/auth/private key.

These are local synthetic checks, not browser-vendor or OS receipt evidence.
Nook ships an installable PWA manifest and service worker, but this does not
prove installation or Web Push delivery on a particular browser or device.
Safari on iPhone/iPad and macOS, Chromium browser and installed-app delivery,
subscription disappearance, real lock-screen appearance, mobile keyboard/a11y
and installed PWA layout remain evidence to collect on real devices. The service
worker caches no requests or private content, so offline operation is not
provided. No native iOS/Android transport exists. WebKit forbids silent Web
Push, so immediate sleeping-device clear/badge-only behavior is explicitly
blocked; foreground read synchronization and badges accompanying visible
alerts are the supported web behavior.

## Target clause acceptance journeys

The 16 October 2026 contract is the full target for an owned US team-chat product replacing Slack, Microsoft Teams and Google Chat. Each numbered journey below is through a user-facing app, HTTP/API, supported client, authorized provider or documented rer command. Build rounds must implement missing journeys and supply measured acceptance; a planned journey is never a passing test. Provider/network fakes belong only at that edge in automated tests; native-device, real migration, real media and hosted claims require the real environments named. App journeys must be used and inspected at 1440 and 390 with realistic data and the named denied-access/error end states; native/assistive-technology cases also run on their supported devices. Keep every permanent clause ID, including C1–C15 aliases, DOCS-001 and ERASURE-001.

The statuses and citations below match the Status table in this revision of CONTRACT.md. Each Current evidence line cites that row’s Evidence files; partial clauses also describe the remaining acceptance gap. A missing clause has no implementing source/test. Shipped subsets named in another clause do not complete a broader acceptance journey. Existing local evidence above remains bounded as stated. The new SSO, hold and compliance clauses define separate authorities; they do not silently grant an ordinary owner/admin DM access or change today’s erasure behavior. Only implementation with its acceptance can change those product paths.

- **NOOK-001 — Current identity and conversation membership (C1).** **Status: done.** Through signed-in HTTP, SSR, search, replay and generated loaders, revoke or expire a session and remove a participant; every subsequent private read/write is refused, including a workspace admin attempting another person’s DM.

  Current evidence: `src/platform/request.server.ts`; `src/platform/storage/context.ts`; `tests/operator-security.mjs`; `tests/storage-guards.mjs`.

- **NOOK-002 — Atomic messages, retries and replay (C2).** **Status: done.** Send through the conversation API, repeat the same intent after a lost acknowledgement, then change its payload; observe one ordered message, the original retry result and a conflict for changed intent. Race edits and delete; replay shows current tombstones without deleted bodies.

  Current evidence: `src/platform/storage/messages.ts`; `src/platform/storage/commands.ts`; `tests/storage-flows.mjs`.

- **NOOK-003 — Fixed DMs and channel membership (C3).** **Status: done.** Create channel/private/DM conversations through the app, add a channel member after earlier messages, and observe full-history disclosure and access. Remove that member and deny history/search/replay/files immediately; refuse DM participant changes and unrelated-admin DM access.

  Current evidence: `src/platform/storage/commands.ts`; `src/team/channels.server.ts`; `tests/team-runtime.mjs`; `tests/storage-flows.mjs`; `tests/browser.mjs`.

- **NOOK-004 — Decisions and commitments (C4).** **Status: done.** From a discussion, record a decision and propose a commitment. Another participant cannot revise the decision or accept for the assignee; the assignee accepts the exact version and reports completion. Reopen history and see human authorship, source context and reported status.

  Current evidence: `src/platform/storage/outcomes.ts`; `src/platform/storage/outcome-history.ts`; `tests/storage-flows.mjs`; `tests/browser.mjs`.

- **NOOK-005 — Read cursors and attention (C5).** **Status: done.** Read a thread from two sessions, reconnect one, and observe monotonic unread recovery with own sends excluded. Refuse read markers beyond the durable frontier; closing Attention does not accept work or mark unseen messages read.

  Current evidence: `src/platform/storage/read.ts`; `src/chat/useReadVisibility.ts`; `tests/storage-flows.mjs`; `tests/browser.mjs`.

- **NOOK-006 — Offline restore (C6).** **Status: done.** Use rer export/reset/import into an empty stopped installation, complete explicit identity recovery, and compare conversations, memberships, outcome versions, attention and downloaded file bytes. A populated destination, altered checksum or invalid graph is refused; no old delivery or session revives.

  Current evidence: `src/platform/storage/portability.mjs`; `scripts/local/transfer.mjs`; `scripts/storage/recover-identities.mjs`; `tests/recovery.test.mjs`; `tests/pilot-journey.mjs`.

- **NOOK-007 — Safe rendering and local binding (C7).** **Status: done.** Post active markup and malformed/oversized bodies through public APIs; markup stays inert and invalid input fails without writes. Cross-origin mutations, foreign sessions and unsafe local origins fail; production output excludes dev admission.

  Current evidence: `src/platform/operator-auth-runtime.mjs`; `src/platform/request.server.ts`; `src/chat/MessageRow.tsx`; `tests/team-security.test.mjs`; `tests/operator-security.mjs`.

- **NOOK-008 — Evidence limits (C8).** **Status: partial.** For a release candidate, reproduce the documented local public-door journeys, then separately record hosted multi-device, provider, migration and capacity results before those target clauses become done. Failed or unmeasured end states remain visible.

  Current evidence: `ACCEPTANCE.md`; `tests/push-journey.mjs`; `tests/pilot-journey.mjs`. The 0.4.0 release gate reran the local core journeys at 1440 and 390 and recorded one hosted run on the RunEditRun Cloudflare account: real sign-in, invitation and mention mail, an update from a populated 0.3.0 installation applying every later migration, and hosted export, removal, redeploy and local restore. Hosted multi-device, real-device push, capacity and full-category acceptance remain unproven.

- **NOOK-009 — Backup and export (C9).** **Status: done.** **Local:** Stop the install, export with `rer export`, import into an empty stopped local install, complete explicit identity recovery and re-export; compare equivalent records, private media bytes and erasure journal. **Hosted:** Sign in as an active owner, follow the hosted backup/export path to download D1 records plus R2 bytes into an owner-held archive, import it into an empty stopped local install and complete identity recovery; compare records, file bytes, rebuilt search and erasure journal. Reject non-owner/expired hosted sessions and any remote restore. Inspect both archives for private records and media, with live credentials, devices and pending deliveries excluded.

  Current evidence: `src/platform/portability.server.ts`; `src/platform/storage/portability.mjs`; `tests/exit-export.test.mjs`; `tests/team-portability.test.mjs`.

- **NOOK-010 — Commitment revision and cancellation (C10).** **Status: done.** Accept a proposal and revise its text/deadline: renewed acceptance is required at the new version. Cancel and create a new proposal to change the fixed assignee. Refuse stale acceptance, cross-conversation moves and author impersonation of completion; cancellation stays terminal in history and deleted source refs reveal no body.

  Current evidence: `src/platform/storage/outcomes.ts`; `src/platform/storage/outcome-history.ts`; `tests/storage-flows.mjs`; `tests/erasure.test.mjs`.

- **NOOK-011 — Cached retries, synchronization and complete history (C11).** **Status: done.** Page beyond the tested history window and reconnect after missed edit/delete events. Repeat a previously successful intent after membership revocation; it must be denied before cached response lookup, with no missing or duplicated durable history.

  Current evidence: `src/platform/storage/history.ts`; `src/platform/storage/commands.ts`; `src/platform/storage/live.ts`; `tests/storage-flows.mjs`; `tests/browser.mjs`.

- **NOOK-012 — Private attachments (C12).** **Status: done.** Upload and bind ordered private files through the app, preview genuine PNG/JPEG and download exact bytes as an authorized participant. Deny outsiders and removed members, reject active/corrupt/oversized input, recover lost-put acknowledgements and verify deletion and backup round-trip.

  Current evidence: `src/platform/storage/files.ts`; `src/team/preview.server.ts`; `src/team/ImagePreview.tsx`; `tests/team-image.test.mjs`; `tests/storage-flows.mjs`; `tests/team-browser.mjs`.

- **NOOK-013 — Calm attention (C13).** **Status: done.** At 1440 and 390, follow a thread, mute its channel, send explicit mentions/urgent requests, snooze and complete triage, and enter quiet time. Restart and sign in elsewhere: preferences persist, due items return under current ACL, and neither triage nor reads accepts responsibility. Automatic follows from authoring, replying, mentions and one-to-one DMs are proved under NOOK-072; an unfollow through `POST /api/messages/:id/follow {follow:false}` ends one.

  Current evidence: `src/family/team-chat/attention.ts`; `src/platform/storage/commands.ts`; `tests/attention.mjs`; `tests/storage-flows.mjs`; `tests/browser.mjs`.

- **NOOK-014 — Email notifications (C14).** **Status: done.** Run the emitted-Worker notification journey through sign-in and settings with only the provider network edge substituted: opt in, mention/propose, fold bursts, hold quiet items, cancel read/deleted/revoked items, restart a retry, expose refusal/uncertainty and use the scanner-safe unsubscribe POST. Inspect that mail contains no private body or file name.

  Current evidence: `src/notify/run.ts`; `src/notify/queue.ts`; `src/notify/compose.ts`; `tests/notify-journey.mjs`; `tests/notify.test.mjs`. Done for the specified behavior. In the 0.4.0 release gate one hosted mention email reached a real inbox through the owner deployment’s SendGrid sender, naming sender and channel without message text; that single receipt establishes no general deliverability or inbox-receipt guarantee.

- **DOCS-001 — Public documentation from Markdown.** **Status: done.** Build and open /docs; every declared page renders, links and anchors resolve, raw HTML remains inert, and every root/docs Markdown source is published or has a recorded exclusion reason. The app Lobby and private workspace keep their existing routes.

  Current evidence: `src/docs/build/site.ts`; `src/docs/build/render.ts`; `docs/site.json`; `tests/docs-site.test.mjs`.

- **ERASURE-001 — Member, message and imported-author erasure.** **Status: done.** Through Team and message erasure doors, preview counts, confirm and resume a pending job. Try an unrelated DM, an insufficient role, self and last owner; deny each. Remove native/imported content and verified R2 bytes, preserve only declared structural tombstones, anonymise audit, and refuse an older archive when the latest erasure journal is supplied.

  Current evidence: `src/team/erasure/service.ts`; `src/team/erasure/graph.ts`; `src/team/erasure/auth-identity.ts`; `src/team/erasure/identity.ts`; `tests/erasure.test.mjs`; `tests/erasure-browser.mjs`. Native/imported cascade, verified blob absence, credential/grant/provider-session removal, independently anonymized auth audit and journal refusal are covered. Logical erasure retains the clause’s stated external-copy and physical-storage limits.

- **NOOK-015 — Web Push (C15).** **Status: partial.** Run pnpm test:push through subscription, preferences, emitted Worker and real alarm; independently decrypt the RFC 8291 packet and verify VAPID, revocation, quiet/read cancellation, per-device folding and visible failure. Separately demonstrate foreground/background/locked-device visible notification, tap authentication and badge reconciliation on supported Safari, Chromium and Firefox devices. **Defaults:** a newly invited member grants browser permission in a fresh profile without opening settings, and a DM, a mention and a keyword hit each show exactly one notification; a channel set to `all new messages` notifies on a colleague's plain message and a channel left at `mentions` does not. **Defaults include automatic follows:** a reply in a thread the member started in a `mentions` channel shows one notification without any explicit follow. **Cross-device routing:** with the member's Chrome page focused and in use, a DM shows on that page and no Web Push reaches their phone's installed PWA; after the page is idle 10 minutes the phone notifies (NOOK-073).

  Current evidence: `src/push/run.ts`; `src/push/subscription.ts`; `src/push/crypto.ts`; `tests/push/journey.mjs`; `tests/push/packet.mjs`; `tests/push-service-worker.test.mjs`. Bounded local Web Push and PWA ship, and enabling push turns on mentions (`src/push/client.ts`); keyword hits and call invites, NOOK-073 cross-device routing in place of the all-device visible-page hold, and browser-vendor/OS receipt and real-device installation evidence are missing. Native transport belongs to NOOK-021 and its push path to NOOK-078.

- **NOOK-016 — Everyday conversations.** **Status: done.** Use two signed-in people at 1440 and 390 to create/join a channel, exchange roots/replies/reactions, open a thread link after reload and edit/delete a message. An outsider and a guest fail to discover private content or expand access. A member leaves a public and a private channel: each disappears from navigation, unread and notifications; they rejoin the public one, are refused rejoining the private one without a manager, and are refused leaving the mandatory default channel.

  Additional current evidence: Mandatory default channels now fence self-leave; genuinely new full members join designated public channels once at first workspace access, with full-history disclosure. Guests and readmitted/restored identities gain no implicit access (`src/team/default-channels.server.ts`; `tests/channel-lifecycle.mjs`). The archived-last-member public restore limitation remains explicit.

  Current evidence: `src/chat/NewMessage.tsx`; `src/team/channel-lifecycle.server.ts`; `src/team/ChannelSettings.tsx`; `src/team/channels.server.ts`; `src/team/ChannelBrowser.tsx`; `src/team/default-channels.server.ts`; `tests/browser.mjs`; `tests/group-dm.mjs`; `tests/channel-lifecycle.mjs`. App-created fixed group DMs, roots/replies/reactions, context links, own edit/delete, scoped discovery/join/leave, private transfer/readmission and mandatory defaults are covered at 1440/390. Archived public channels remain discoverable as read-only history after their last member leaves; a current owner/admin joins before restoring.

- **NOOK-017 — Composition and personal workspace.** **Status: partial.** Compose formatted text/code and an attachment, leave and resume a draft on each supported client, deliberately interrupt a send and reconcile it once. Switch accounts/workspaces and inspect draft isolation; mark unread and change status/time zone without changing work acceptance. Set a status to clear after 30 minutes and see it disappear on another client at that time, across a restart. Define title, phone and manager fields, fill them and find a person by department in the people directory at 1440 and 390; a guest sees only people in their granted channels and no hidden field. Paste 50,000 characters: the composer offers a snippet or a split, and posting as a snippet yields one message with a previewable text attachment; an API post of 40,001 characters is refused with `message_too_long`, and one of 40,000 posts whole. Type `*bold*`, `_italic_`, `~strike~`, `` `code` ``, a fenced block, `> quote` and `- item`: each converts as typed, one undo restores the literal text, and the plain-text export keeps the content. Type `/` and see the built-in commands before app commands. Run `/remind me tomorrow at 3pm to send the deck`, `/invite @ana #sales`, `/topic Q4 launch`, `/rename #sales-us`, `/mute`, `/dnd 1 hour`, `/status :palm_tree: Out until Monday`, `/msg @ana hi`, `/huddle`, `/gif thumbs up`, `/shrug ok`, `/collapse` and `/leave`: each has the same effect, permission check and audit as its menu action. `/rename` by a member without rename permission is refused privately with the reason, and `/wat` posts nothing and offers to send it as text. Open Drafts & sent and find an unsent draft from another channel, a scheduled message (change its time there) and yesterday's sent message.

  Current evidence: `src/chat/Composer.tsx`; `src/chat/composition/useCompositionDelivery.ts`; `src/commands/useCommands.tsx`; `src/profiles/server.ts`; `src/personal/workspace.server.ts`; `src/personal/typing.server.ts`; `tests/composition-browser.mjs`; `tests/profiles.mjs`; `tests/personal.mjs`; `tests/personal-browser.mjs`; `tests/team-portability.test.mjs`; `tests/storage-flows.mjs`. Web Markdown source with accessible rich preview, typed-format conversion/undo, person/channel mentions, emoji, text export, exact-byte previewable snippets and resumable split sends ship alongside durable Drafts & sent. Built-in slash commands use current-authority APIs and private confirmations. Profiles, chosen time zones, expiring statuses, optional typing/presence, field privacy, a fully paged 5,001-person directory, private sidebar sections, explicit mark unread and installation links ship. Browser journeys cover 1440/390 and lost-send acknowledgement across reload; archive/erasure retain their guarantees. The conversation-list cap no longer limits draft enumeration. Remaining: Native-client draft/status/workspace-switch journeys, calling/GIF service effects for `/huddle` and `/gif`, app-command ordering/name reservation and Slack-compatible length errors remain under NOOK-021/022/025/063/070. Installation switching is by separate-origin links and independent sign-in; no native workspace picker is claimed.

- **NOOK-018 — Invitations, roles, guests and offboarding.** **Status: partial.** Invite a member and scoped guest via Team, confirm once, browse/join as each and refuse guest expansion or owner DM snooping. Deactivate a person signed in twice, reactivate, and prove both old sessions remain invalid and explicit regrant is required. **Bulk, link and domain doors:** paste 50 addresses including one duplicate and one invalid; the preview flags both, 48 invitations are sent, and each person who accepts lands in the default channels. Create a 7-day invitation link limited to 10 uses: the 11th use is refused, revoking the link stops further joins, and each use appears in the audit log. Approve a verified `example.com`: a new `@example.com` person joins as a member with 2FA enforced, while an `@other.com` address and an attempt to approve `gmail.com` are refused. With member invitations restricted to admins, a member's invitation request reaches an admin, who approves it, and the invitee joins.

  Current evidence: `src/team/invitations.server.ts`; `src/team/access.ts`; `src/platform/operator-auth-runtime.mjs`; `tests/team-runtime.mjs`; `tests/operator-security.mjs`. One-address confirmed email invitations, member/guest grants, deactivation and explicit regrant ship; bulk/CSV invitations, invitation links, approved-domain join and invitation requests are missing.

- **NOOK-019 — Search conversations and files.** **Status: done.** Find an old imported reply and a phrase inside a permitted PDF/text attachment using author/date/channel filters; open context from each client. Search "Q3" and "HR" with a channel and date filter and get every authorized message and file containing those tokens. Page an 80,000-message corpus completely with no duplicate or missing result; remove membership/delete a file and confirm its snippets, counts and cached results disappear. Type `from:@jane in:#sales has:link before:2026-10-01` and get the same results as the equivalent filters, shown as chips; `during:september` returns September messages in the searcher's time zone, and `-draft` excludes matching messages. Open a private channel's Files tab and see its native and imported files; a non-member sees neither the tab nor those files in the workspace Files view.

  Current evidence: `src/search/server.ts`; `src/search/parse.ts`; `src/search/terms.ts`; `src/search/files.ts`; `src/chat/SearchView.tsx`; `src/files/server.ts`; `src/files/FilesView.tsx`; `tests/search.mjs`; `tests/search-browser.mjs`; `tests/files.mjs`; `tests/files-browser.mjs`; `tests/saved-search.mjs`; `tests/slack-import/journey.mjs`. Combined Unicode terms, exact phrases, token prefixes, substring and exclusion search, every typed modifier, timezone date ranges, conversation types, current-ACL filenames and extracted plain-text/PDF contents ship. Unsupported and unindexed files are named, not represented as searched (PDF extraction: 100 pages / 1 MiB of text). The emitted Worker journey pages all 80,000 corpus messages without duplicates or omissions, then refuses removed membership. Browser journeys at 1440/390 cover PDF excerpts, removable filters, query errors, source context and revoked results; existing Files journeys cover native/published imported files. Native client and broader file admission remain NOOK-021/061.

- **NOOK-020 — Saved items and channel pins.** **Status: done.** Save a DM and pin a channel message, retrieve both after restart on another device, then remove membership and erase the source. Private saves stay private and every unavailable item loses its excerpt.

  Current evidence: `src/team/saved.server.ts`; `src/team/saved-policy.ts`; `src/team/saved-reminders.server.ts`; `src/chat/SavedView.tsx`; `src/chat/SavedReminder.tsx`; `src/chat/ReminderCards.tsx`; `src/chat/PinsView.tsx`; `tests/saved-search.mjs`; `tests/saved-reminders.mjs`; `tests/saved-reminders-browser.mjs`; `tests/team-portability.test.mjs`. Private ordered message/file/link saves, shared pins with actor/time, due reminders with edit/cancel/snooze/dismiss, restart and second-session recovery, quiet holds, current-ACL firing and erased-source tombstones are covered on the web at 1440/390. Reminders create no unread, external notification or accepted work. Native clients remain NOOK-021’s separate missing implementation.

- **NOOK-021 — Native clients and dependable device catch-up.** **Status: missing.** Install production-signed apps on real iOS/Android and each desktop OS and sign each in through a NOOK-074 path, never a pre-seeded session. In foreground, background, force-closed and locked states send a mention/DM/call invite, observe alert/badge and tap to context; disable permission and expose the reason. Read on another device, disconnect/reconnect, race a send retry and revoke membership: converge once, purge revoked caches and verify logout isolation. Share a photo and a PDF from the iOS and Android share sheets into a private channel thread and see each post once. **Default alerts:** a freshly invited member installs the iOS app and allows notifications without opening settings; a DM, a mention and a keyword hit each alert once; repeat on Android and on one desktop OS. **Delivery bar:** on a real-device fleet of at least two iOS and two Android phones at the published OS floor plus each desktop OS, send 500 mixed eligible events (mentions, DMs, keyword hits, broadcast mentions and call invites) spread across foreground, background, force-closed and locked states over 24 hours. Record each event's server commit time and device display time from device logs, then compare to the bar: ≥ 99.5% displayed, p95 ≤ 5 s and p99 ≤ 30 s commit-to-display, locked-phone call ring ≤ 5 s at p95, and every badge equal to the authoritative unread plus Attention count within 10 s of reconnect. Every undelivered event appears as `provider-unconfirmed` or `device-unobserved` in the device delivery view and owner report; a single silent miss fails the journey. Install on a device below the floor and see the unsupported notice. A web-Push test alone cannot satisfy this journey. **From a customer installation:** the fleet signs in to an installation on a fresh Cloudflare account that is not the publisher's and is reached only through NOOK-078's push path; a run against a publisher-operated installation does not count. **Automatic follows and active-elsewhere routing:** a reply in a thread the member authored alerts their phone without any explicit follow while they are not active on desktop; while they actively use the macOS app the same reply alerts only the desktop, and their phone alerts after the screen locks unless it was read first. Events held for active-elsewhere in the 500-event run appear as `held-active-elsewhere` or are timed from release, never counted as displayed or silently missing.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-022 — In-context voice, video and screen sharing.** **Status: missing.** From a private channel and DM run a three-person real audio/video call across desktop and phone, share a window, read captions, switch devices, interrupt networking and reconnect. Remove a participant and deny further media access; an outsider cannot join with a copied link. Refused microphone/camera permission and failed relay show actionable states. At 50 participants with 25 cameras on across desktops and phones, measure p95 join time ≤ 3 s, audio continuity (no gap over 500 ms in a 10-minute session on the target network) and screen-share legibility (10-pt text readable at 390 width); a 51st joiner sees the full state.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-023 — Zoom, Google Meet and Teams meetings.** **Status: missing.** For each named provider connect a test tenant, create and join from a channel and DM on phone/desktop, reschedule then cancel, and revoke consent. Observe provider-confirmed links and honest failure; a private recording link never broadens provider access.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-024 — Asynchronous clips, transcripts and call artifacts.** **Status: missing.** Record a clip from phone and desktop, play with captions and seek from transcript; record a consented huddle and inspect its audience. Reject an outsider, simulate failed processing, correct a transcript and export/delete or hold the artifact without losing policy state.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-025 — App and bot platform.** **Status: missing.** Install an app as owner, subscribe only one channel, post a signed incoming event, invoke a slash command and click an interactive approval. Replay/forge payloads, exceed a rate limit, copy a private event ID and revoke the app: deny escalation, avoid duplicate effects and show delivery/uncertainty with secrets redacted. An app with the DM scope opens one app DM with a member; the member mutes, blocks and unblocks it, and posts are refused while blocked. The member adds the app to a private channel and removes it, and the audit log shows both; the app's token cannot list or read any other DM, group DM or private channel. An app without the channel-management scope cannot create a channel.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-026 — Workflow builder and durable scheduled work.** **Status: missing.** Build a recurring stand-up form that posts a channel summary and proposes work only for explicit acceptance. Publish, trigger once, pause during an approval wait and restart; no duplicate post or unauthorized write occurs. Refuse a revoked connector and expose the failed step plus a safe human resume choice. A welcome workflow DMs a person exactly once when they join `#onboarding`; adding :ticket: to a message runs the reaction workflow once for that message even when two people add it; intro pairing over a 9-member channel produces four pairs and one trio with no one left out.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-027 — Engineering and project integrations.** **Status: missing.** Connect each named service, route a selected project/repository event, act from a card and follow a linked issue/PR from open to complete to reopened. Retry its webhook, remove source permission and revoke the grant: exactly one authorized effect and no leaked project context. Vector remains the authoritative work record.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-028 — Support, sales and operational signals.** **Status: missing.** For each named service route a real sandbox case/account/alert event, inspect an authorized preview, approve a supported write and observe source-confirmed state. Deliver duplicate/recovery events, disconnect the source and remove channel access; keep one linked thread, no false completion and a visible failed/uncertain action.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-029 — Connected documents and knowledge.** **Status: missing.** Connect each named provider, share an authorized document into a matching channel, retrieve its card/text as an allowed member and refuse a source-denied member. Revoke provider sharing or disconnect, refresh search/agent context and show unavailability without cached excerpts or broadened access.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-030 — Calendars, availability and meeting reminders.** **Status: missing.** Connect both calendars, create a cross-time-zone meeting from a DM, accept/change/cancel it at the provider and see exactly one current card/reminder. Show free/busy without private title access, cross a daylight-saving transition and revoke the grant before a scheduled action. Turn on calendar-driven status: a private meeting sets "In a meeting" without its title and clears at its end, and a hand-set status is left untouched.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-031 — Shared channels between organizations.** **Status: missing.** Two independently administered organizations approve a channel, exchange messages/files/calls and install one narrowly scoped bot; start and accept an external DM, then block it through one organization's policy. Exercise a single-channel guest, denied directory lookup, conflicting retention/export policy, member removal and full org disconnect. Every client/search/agent/API loses revoked access while permitted historical copies are explicitly accounted for.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-032 — Recurring quiet schedules and notification policy.** **Status: partial.** Set a weekday quiet schedule and channel override, cross midnight/DST and restart without a page open. Send routine/mention/urgent events and a message containing the recipient's keyword "invoice" from another account (one keyword item in a readable channel, none in a muted or unreadable one), read on a second device and compare the activity feed, held items, badges and provider attempts with the recipient’s stated rules. **Per-conversation levels:** a freshly invited member allows notifications without opening settings, and a DM, a mention and a keyword hit each alert once. They set `#incidents` to `all new messages` on mobile only: a colleague's plain message there alerts their phone but not their desktop, while a routine message in a `mentions` channel alerts nothing. Setting `#random` to `nothing` suppresses even an `@here`. During quiet time the `#incidents` alerts are held and released by the schedule. The exception list shows `#incidents` and `#random`, and resetting each returns it to `mentions`. First sign-in tells the member that email is off, and its one-action opt-in produces one 15-minute bundled email for a mention and a DM while away. **All thread replies:** with `#incidents` also set to all thread replies on mobile only, a reply in a thread the member never touched alerts their phone (when they are not active on desktop, NOOK-073) and not their desktop, the exception list shows the setting, and resetting it returns `#incidents` to followed threads only.

  Additional current evidence: Web per-conversation all/mentions/nothing levels and all/followed thread modes now persist, drive current-ACL Attention/push/email policy, cancel pending delivery after silence and expose an exception list/reset (`src/team/conversation-notify.server.ts`; `src/chat/ConversationNotifications.tsx`; `tests/threads.mjs`; `tests/push/routing.mjs`; `tests/notify-journey.mjs`). Web Push mobile overrides are covered under NOOK-072; recurring schedules, keywords, native routing and org defaults remain pending.

  Current evidence: `src/team/conversation-notify.server.ts`; `src/chat/ConversationNotifications.tsx`; `src/platform/storage/messages.ts`; `src/push/policy.ts`; `src/notify/run.ts`; `tests/threads.mjs`; `tests/push/routing.mjs`; `tests/notify-journey.mjs`. Web conversation levels (all new messages, mentions, nothing), all-thread replies, mute exclusivity, exception list/reset, current-ACL routing, delivery-time cancellation and durable archive/erasure integration ship. Nothing silences pending/new email and push while explicit mentions/urgent requests remain in Attention. Web Push phone/tablet level and thread overrides use explicit per-device classification under NOOK-072. Recurring/time-zone schedules, keywords, native classification and active-elsewhere routing, channel-broadcast replies, org/new-member push defaults and email onboarding remain missing.

- **NOOK-033 — Personal and channel reminders.** **Status: done.** Schedule a personal message reminder and recurring channel reminder, close every client and restart before due. Observe one eligible reminder at the chosen time, snooze/edit/cancel it, revoke the creator’s channel access and confirm no unauthorized later post. `/remind #standup "Post your update" every weekday at 9am` shows its parsed recurrence and posts at 9:00 in the creator's time zone on weekdays only, across a DST change; `/remind me in 20 minutes to call Ana` fires once 20 minutes later; `/remind me sometime soonish` asks again and saves nothing.

  Current evidence: `src/reminders/service.ts`; `src/reminders/runner.ts`; `src/reminders/parse.mjs`; `src/reminders/ReminderEditor.tsx`; `src/reminders/RemindersView.tsx`; `tests/reminders.mjs`; `tests/reminders-browser.mjs`; `tests/exit-export.test.mjs`. Web/API reminders parse and preview before saving, deliver from the real durable alarm after restart, and recheck source, recipient and posting access atomically. Personal reminders appear in Attention and respect quiet time; channel prompts post once per occurrence. Edit, snooze, complete and cancel are independent of reads and work acceptance. Backups pause pending reminders for review; native clients remain NOOK-021’s separate missing implementation.

- **NOOK-034 — Scheduled and recurring messages.** **Status: done.** `tests/scheduled.mjs` proves the emitted Worker/D1 alarm and rule checks; `tests/scheduled-browser.mjs` proves compose with files, pending, edit/resume, cancel and refusal at both widths. `tests/erasure.test.mjs` and `tests/exit-export.test.mjs` prove template custody and paused restore. Schedule a one-off and weekly stand-up, change the time across DST, restart at due time and replay a scheduler claim. See one post per occurrence, then pause/cancel and remove posting access: no new post or hidden failure.

  Current evidence: `src/scheduled/service.ts`; `src/scheduled/runner.ts`; `src/scheduled/files.ts`; `src/scheduled/time.mjs`; `src/scheduled/ScheduleEditor.tsx`; `src/scheduled/ScheduledView.tsx`; `tests/scheduled.mjs`; `tests/scheduled-browser.mjs`; `tests/erasure.test.mjs`; `tests/exit-export.test.mjs`. Web/API one-off and recurring sends, DST previews, attachment custody, pause/edit/resume/cancel, restart and exactly-once occurrence commits ship. Delivery rechecks current membership and posting permission; a refusal is visible. Restore pauses schedules for review. Native clients remain NOOK-021’s separate missing implementation.

- **NOOK-035 — Channel recaps and catch-up digests.** **Status: missing.** Request a channel/thread recap and daily unread digest over contradictory discussions and inaccessible channels. Check every factual point against a source link, remove access before delivery, correct a claim and cancel the schedule. No private snippet or invented acceptance survives.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-036 — AI search with cited answers.** **Status: missing.** Ask an answerable, contradictory and unanswerable question with private files and a hostile document in the corpus. Follow citations, revoke a source and repeat as a different member: deny cross-scope context, abstain where unsupported and perform no embedded instruction or external write.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-037 — SSO, SAML and lifecycle provisioning.** **Status: missing.** Use test tenants for all three IdPs, enforce SSO, rotate signing keys and reject wrong audience/issuer/replayed/expired assertions. SCIM-create a group/member, map one channel, suspend/delete and replay the event; every client and grant loses access without deleting preserved evidence. Exercise audited owner recovery without a blanket bypass.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-038 — Retention, legal hold and preservation.** **Status: missing.** Apply a short retention policy, hold a selected member/date range, edit/delete held messages and expire their files. Ordinary participants lose deleted content, a custodian preserves exact history, and an unauthorized admin cannot retrieve it. Release the hold and finish the queued erasure with actual byte verification and audited counts.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-039 — Compliance search and controlled exports.** **Status: missing.** Open a case, obtain required approval, export a held DM/file plus revision history and verify manifest completeness and hashes. Try the same through an ordinary admin session and deny it. Revoke the custodian mid-job, expire the download and inspect a durable audit of search, approval and retrieval.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-040 — Information protection and data handling.** **Status: partial.** Label a private channel, attempt a restricted external share, connector post, export and AI retrieval, and observe the configured block/warning. Exercise an approved override and revoke it; inspect policy history, secret redaction and deletion of derived content after source erasure.

  Current evidence: `src/platform/storage/context.ts`; `src/platform/storage/files.ts`; `src/push/crypto.ts`; `tests/team-security.test.mjs`. Current-membership private-message/file access and encrypted push exist; labels, DLP, organization AI policy and cross-tool enforcement are missing.

- **NOOK-041 — Slack migration and cutover.** **Status: partial.** Use an authorized real Slack workspace export plus synthetic adversarial coverage, preview without writes, resolve an identity collision and a missing file, import public/private/DM/shared histories, verify complete counts/bytes/threads/search and deny outsiders. Interrupt/resume and undo a batch after native activity, confirming refusal where undo would destroy that activity. The preview lists every integration in the export with its disposition, and repointing one incoming webhook delivers to the mapped channel. **Slack Pro consented path:** on a Slack Pro test workspace with a private channel, a 1:1 DM, a three-person group DM, custom emoji, a user group and files, import the official public-only ZIP, then have members grant their Slack user tokens. Two of three group-DM members consent: the group DM stays unpublished and the cutover report lists it with its member count and the missing consent. Both 1:1 participants consent: the DM imports with its threads and file bytes and only those two can read it. The private channel's manager consents: it imports to its exact membership. Revoke one member's grant mid-run and see no further fetch with that token in the Slack request log. An outsider, and the owner and an admin who are not members, find none of this content by search, link, export or API. Custom-emoji reactions and an `@group` mention render after import. **Cutover invitations:** import a Slack Pro export with 120 active members, 3 guests and 5 deactivated users. The preview proposes 120 member and 3 guest invitations and excludes the 5 deactivated users and every bot. Send them in one action at a scheduled cutover time across a restart. An accepting member sees their imported messages attributed to them, a guest sees only their mapped channels, and the report shows joined and pending counts. No private channel or DM audience changes as people join. The integration checklist for an export containing Polly, Geekbot and Donut names NOOK-070 polls and the NOOK-026 stand-up and intro-pairing templates. **Slack links:** an imported message linking to another imported thread opens that Nook thread; a link to a private channel that was not imported, or that the reader is not in, shows "Slack message not imported" or "Not available to you" with the original URL and no content; a Slack permalink pasted after cutover opens the mapped Nook message; the cutover report counts resolved and unresolved links. **Personal setup:** a member with a consented grant finds their future Slack reminders as Nook reminders that fire on time and their starred messages as saved items, visible to no one else; onboarding lists sidebar sections, notification levels, mutes, scheduled messages and Later items as needing to be set again. The Slack Connect journey is NOOK-076's, and the final catch-up journey is NOOK-077's.

  Current evidence: `src/imports/archive-plan.mjs`; `src/imports/history.ts`; `src/imports/ImportWizard.tsx`; `src/imports/slack.mjs`; `tests/slack-import/journey.mjs`; `tests/pilot-journey.mjs`. Reviewed resumable public-channel JSON ZIP history, file choices, threads, bot provenance and guarded undo ship on synthetic fixtures; private/DM/shared import (including the consented member-token path for Free/Pro exports), custom emoji and user-group import, the integration inventory with dispositions, Slack-link resolution in imported history, personal reminder and starred-item import, full metadata parity and real-source cutover remain missing.

- **NOOK-042 — Microsoft Teams migration.** **Status: missing.** Extract a real test tenant containing channels, private/shared channels, 1:1/group/meeting chats and protected files; page every source set, preview, import and verify counts, chronology and visibility. Revoke an export scope, interrupt/resume and undo without deleting later native work; show each omission.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-043 — Google Chat migration.** **Status: missing.** Import a real Workspace test export with spaces, threaded replies, DMs and files plus an externally owned space omitted by source policy. Compare coverage and exact visibility, interrupt/resume and undo after native activity, and confirm no notifications, accepted tasks or outsider access.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-044 — Campfire ONCE migration.** **Status: done.** Take a consistent real Campfire test-instance backup with open/closed rooms, DMs and uploads, preview and migrate it, then compare messages/files and deny unrelated members. Reject an incomplete/unsupported backup and exercise resume and safe undo.

  Current evidence: `src/imports/campfire.mjs`; `src/imports/campfire-records.mjs`; `src/imports/campfire-capture.mjs`; `src/imports/campfire-effects.mjs`; `src/imports/campfire-reviewed.mjs`; `src/imports/service.ts`; `src/imports/CampfireWizard.tsx`; `docs/campfire-import.md`; `tests/campfire-import/fixtures/README.md`; `tests/campfire-import/journey.mjs`; `tests/campfire-import/browser.mjs`. Version-declared consistent official Campfire Express format-1 SQLite/upload backups are reviewed through the shared import pipeline with exact public/private/DM kinds, mapped participant sets and fixed DM rosters, source authors and saved times/rich text, provenance and original file SHA-256. The genuine upstream HTTP-created fixture reconciles five rooms, four identities, ten messages and three files; unsupported/incomplete or ambiguous backups are refused before publication. Explicit injective identity association creates no account, credential or source-role grant and adds no importer to a DM. Durable apply/lost-ack resume avoids duplicates; clean guarded undo removes only owned unchanged effects, and native activity blocks undo without losing later messages. Both-width UI journeys include the guide, review, completion and populated imported history. The supported source version has no native reply relationship; none is invented. Rails backup layouts and other schemas are explicitly unsupported; declared size/record bounds refuse rather than truncate.

- **NOOK-045 — Zulip migration and topic continuity.** **Status: missing.** Export a real Zulip test organization with two topics in one channel, private conversations and uploads; import and navigate each topic independently, inspect consent omissions and verify private audiences. Resume once without duplicates and undo while preserving later native work.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-046 — Mattermost migration.** **Status: done.** Export a real Mattermost test deployment spanning two teams, private channels, DMs, replies, saved/pinned items and attachments. Review/map roles, import and find every declared item while denying outsiders; interrupt/resume and undo without removing subsequent Nook messages.

  Current evidence: `src/imports/mattermost.mjs`; `src/imports/mattermost-records.mjs`; `src/imports/mattermost-capture.mjs`; `src/imports/mattermost-effects.mjs`; `src/imports/mattermost-reviewed.mjs`; `src/imports/MattermostWizard.tsx`; `docs/mattermost-import.md`; `tests/mattermost-import/fixtures/README.md`; `tests/mattermost-import/journey.mjs`; `tests/mattermost-import/browser.mjs`. Supported Mattermost Server 12 bulk format-1 ZIPs preserve teams, public/private channels, fixed DM/group rosters, original authors and millisecond times, replies, supplied reactions, checksum-verified attachments/custom emoji, private saves and shared channel pins. Every source role is explicitly retained as history only; identity mappings create no account, credential or custodian grant. The genuine official-image deployment fixture reconciles 73 source records, nine conversations, four people/two built-in bots, 33 messages, three files and one custom emoji. Upstream omits direct/group root reactions: the API readback retains its four-reaction expectation, while the ZIP supplies three; preview explicitly names the unknown source omission, and supplied direct reactions are independently exercised. Seven clause-tagged emitted Worker/D1 checks cover refusal of incomplete/unsupported/ambiguous inputs, exact audiences and hashes, inert history, an actual interrupted multi-batch checkpoint/restart with deduplication, guarded undo preserving native activity, clean reversal, and browser use at 1440/390. Original source credentials never become Nook authority; private saved identities are excluded from ordinary provenance/readable exports. Source bounds and unknown source facts are documented rather than silently truncated or invented.

- **NOOK-047 — Readable portability and controlled exit.** **Status: done.** Export a member-scoped conversation and all conversations and DMs the member currently belongs to; exclude a private conversation they never joined and one they left, and refuse subsequent access after membership revocation. As a current workspace owner, attempt a whole-workspace export with the default-off policy disabled and refuse it. Enable a versioned workspace export policy: every member receives the announcement and the audit records who, when and the policy version before an export includes other private conversations. Export the populated workspace, private conversations and DMs included, and verify that the export states that policy version; disabling the policy or losing ownership blocks further workspace export access. Attempt another person’s DM as an admin who is not an owner and refuse it. Exclude protected held copies and name that exclusion without revealing any hold inventory. Include an older membership event lacking direction or time: the readable report says "unknown", while exact joins and leaves after adoption retain their recorded direction and time. Read the HTML offline, enumerate JSON/file hashes against the source, cancel/resume a large job, and verify all omissions are named. A successful operational backup alone does not prove readable exit.

  Current evidence: `src/exit/authority.ts`; `src/exit/store.ts`; `src/exit/pages.ts`; `src/exit/files.ts`; `src/exit/catalog.ts`; `src/exit/format.ts`; `src/exit/ReadableExport.tsx`; `src/exit/OwnerExportPolicy.tsx`; `migrations/0062_workspace_readable_export.sql`; `docs/readable-export.md`; `tests/readable-export.test.mjs`; `tests/readable-export-archive.test.mjs`; `tests/readable-export-browser.mjs`. Versioned JSON/JSONL and self-contained offline HTML cover member conversations and owner-authorized whole-workspace exit, complete paged native/imported history, membership records, versions/tombstones, reactions, decisions, acceptance history, source mappings and checksum-verified file bytes. Policy changes atomically announce their version to every active member and audit owner/time/version/recipient count; each workspace export states that version. Workspace authority is default-off, explicitly enabled by a current owner, version-fenced on every report/page/file and reset on operational restore; ordinary admins remain refused another person’s DM. Cancel/reload/resume, exact counts, offline reading and both-width journeys name NOOK-047. Non-secret workspace policies are included; unpublished sources, credentials, held copies, unsupported external artifacts, unrecorded pre-adoption history and not-yet-shipped workflow/app/agent records are explicitly named omissions. No copied bodies or file bytes persist in jobs; browser assembly needs memory for the selected data.

- **NOOK-048 — Team administration and reporting.** **Status: missing.** Populate a US 35-person team with guests, a private management channel, missed notifications and overdue linked work. Compare filtered report totals to authorized records, export CSV, remove a viewer’s access and verify both aggregates and drill-through stop exposing that scope; show a failed sync as incomplete data. Repeat totals and drill-through at the NOOK-049 capacity installation (1,000 members, 5,000 channels).

  Current evidence: No implementing source/test; journey pending.

- **NOOK-049 — Reliability, performance and operating recovery.** **Status: partial.** On the supported hosted configuration, seed 1,000 members, 5,000 channels, 25 million messages over 7 years and 2 TiB of files; drive 1,000 connected clients at 50 messages/s with 200/s bursts and a 1,000-member default channel, and measure sent-to-visible p95/p99, last-recipient fanout, 24-hour reconnect catch-up, complete reconnect count and search latency against the stated objectives. Page the people directory and channel browser past 1,000 and 5,000 entries and find the last entry by search. Interrupt fanout/provider access, restart workers, upgrade without data loss, restore from an owned backup within RTO and compare outcomes to the published objectives and component status.

  Current evidence: `src/platform/storage/live.ts`; `src/platform/storage/messages.ts`; `scripts/storage/measure.mjs`; `tests/storage-flows.mjs`; `tests/recovery.test.mjs`. Normalized D1/R2, Durable Object replay and local restart/restore checks exist; hosted service levels, media/platform failure recovery, directory paging past 1,000 and the stated capacity objectives remain unproven.

- **NOOK-050 — Owned installation and Base replacements.** **Status: partial.** Follow README installation, first-run setup and invited sign-in; upgrade existing data, run doctor, export/reset/recover and use the configured hosted owner claim. Check invalid config and missing secrets fail closed, operator disk custody is disclosed and no private value reaches logs/builds. Reproduce on a real supported owner account and inspect actual USD provider usage separately from local/fake-account tests. Install with an explicit data jurisdiction and confirm setup and doctor show it. Open the published reference cost for 50 and 300 members, check its unit costs and assumptions against the measured release figures, and compare the installation's actual cost per active member with it. Open the subprocessor list in `/docs` and doctor: it names the NOOK-078 Nook Push Gateway with its region, what it sees, availability objective, price and terms, and the reference estimate shows the gateway's price as its own line; switch to owner-credential mode and see the gateway leave the list and the developer account fees appear.

  Current evidence: `src/platform/operator-auth-runtime.mjs`; `src/platform/owner-claim.server.ts`; `src/platform/portability.server.ts`; `scripts/installer/local.mjs`; `tests/installer-workflow.mjs`; `tests/owner-deploy.test.mjs`; `tests/part6.mjs`. Base-backed local lifecycle, owner claim, portability and fake-account deployment checks exist; live hosted/provider/native operating proof, data-location choice, full cost reporting, the published subprocessor list naming the NOOK-078 gateway and the published 50/300-member reference cost with its gateway and owner-credential lines are missing.

- **NOOK-051 — Auditable authority and actions.** **Status: partial.** Exercise membership revocation, export, erasure and an approved bot/workflow action, then filter/export their log through admin doors. Deny members and an erased actor; anonymize that actor and retain the action facts. Interrupt an external step and see uncertainty rather than a forged completion.

  Current evidence: `src/team/erasure/audit.ts`; `src/base/modules/operator-auth/accounts/admin.mjs`; `tests/erasure.test.mjs`; `tests/operator-auth.test.mjs`. Auth and anonymized erasure audit foundations exist; unified administrator log, hold/export/app/agent coverage and filters are missing.

- **NOOK-052 — Accessible, responsive daily use.** **Status: partial.** At both widths and on native clients, use keyboard and VoiceOver/NVDA to send/reply/search, accept work, upload, join a captioned call, migrate, change a policy and pause an agent. Inspect realistic long names/history, enlarged text, focus after deletion/reconnect and error announcements; run scoped automated accessibility checks and record manual limitations. **Quick switcher and shortcuts:** keyboard only on macOS, Windows, Linux desktop and the web, ⌘K/Ctrl K then "inc" and Enter opens `#incidents`; a private channel the member is not in never appears, even by exact name; ⌘⇧A opens All unreads and ⌘⇧T Threads; Esc marks the current conversation read and ⇧Esc marks all read with undo; ↑ in an empty composer edits the last message; ⌘/ lists every shortcut; a screen reader announces each result.

  Current evidence: `src/chat/QuickSwitcher.tsx`; `src/chat/QuickNavigation.tsx`; `src/chat/quick-threads.ts`; `src/chat/quick-people.ts`; `src/chat/useLastMessageEdit.ts`; `src/platform/storage/latest-edit.ts`; `tests/keyboard.mjs`; `tests/keyboard-gaps.mjs`; `tests/quick-switcher.mjs`; `tests/accessibility.mjs`; `src/reminders/RemindersView.tsx`; `tests/reminders-browser.mjs`. Web All unreads and mark-all undo ship under NOOK-071. Up in an empty composer and its visible equivalent select the current-authorized latest editable own root/reply even outside the loaded window; drafts, uploads, pending sends, IME and modified arrows stay intact. Root, thread and inline editing retain focus at 1440/390. The quick switcher pages all followed threads and people, resolves ordinary recent thread visits after unfollow/reload under current ACL, and isolates accounts. The unchanged reminder journey also proves immediate snooze/cancel at both widths after the list-version race was fixed. Native shortcuts/text scaling, manual VoiceOver/NVDA, full WCAG 2.2 AA evidence and acceptance of call/agent/native journeys remain pending with their underlying implementations.


- **NOOK-053 — Conversation notes and lightweight lists.** **Status: missing.** Create and revise a private channel note/checklist, link a provider document, propose an item to another person and require their exact acceptance. Remove a member, export history and delete/hold the note; all sources keep their distinct permissions and authority.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-060 — Organization policy and channel lifecycle.** **Status: partial.** As owner create a delegated channel admin and a user group, rename/archive/restore a populated channel, transfer ownership and schedule guest expiry. Preview/refuse a private-to-public conversion that would expose earlier history, exercise group mentions and custom emoji, and deny app/compliance/DM operations outside the delegated grant. Verify expiry/revocation across phone, desktop, search and bot access. Restrict channel creation and guest invitation to admins and set a 15-minute edit window: a member's create, invite and late edit are refused through app and API, and a new member auto-joins both default channels. Turn invitation links off and approve one domain: creating a link is refused and the domain appears in the approved list. Set `#announcements` to `all new messages` and email on for new members: a member who joins afterwards starts with both, and an existing member's settings are unchanged.

  Additional current evidence: Versioned public default-channel policy, owner-only mandatory requirements, body-free history, designated-channel archive refusal, atomic first admission and archive/erasure handling now ship (`src/team/DefaultChannels.tsx`; `src/team/default-channels.server.ts`; `tests/channel-lifecycle.mjs`; `tests/team-portability.test.mjs`). Group/delegated-role and other organization policies remain pending.

  Current evidence: `src/team/channel-lifecycle.server.ts`; `src/team/default-channels.server.ts`; `src/team/DefaultChannels.tsx`; `src/team/ChannelSettings.tsx`; `tests/channel-lifecycle.mjs`; `tests/team-portability.test.mjs`. Versioned management transfer, name/topic, archive/restore, write fences and action history ship. Owners/admins configure public defaults with full-history disclosure and audit; only owners change mandatory requirements. Designated defaults cannot be archived until removed. Admission, archive recovery and erased audit attribution preserve audience. Delegated/custom roles, groups, description/privacy conversion, guest expiry, invitation/domain and creation/edit/delete policy, custom emoji, group defaults and org notification defaults remain missing. Web workspace/channel broadcast permission, named senders and ignore choices now ship under NOOK-065 (`src/broadcast/settings.ts`; `tests/broadcast.mjs`); user-group, app/webhook/workflow and native broadcast-policy acceptance remain incomplete.

- **NOOK-061 — Any office file, large uploads, previews and malware scanning.** **Status: partial.** Upload and download a .docx, .xlsx, .pptx, .csv, .zip, HEIC photo, animated GIF and an MP4 screen recording within 5% of the 1 GiB limit at 1440 and 390 and on native clients; interrupt one upload mid-way and resume it with no duplicate; preview each type in-app and compare downloaded bytes by SHA-256. Upload the EICAR test file and see it quarantined for uploader and recipients with no download or preview path. Stop the scanner and see new files held as scanning. Block `.exe` as admin and see app, API and webhook uploads refused with no stored bytes; a file of 1 GiB plus one byte is refused.

  Current evidence: `src/platform/storage/files.ts`; `src/team/preview.server.ts`; `tests/team-image.test.mjs`; `tests/storage-flows.mjs`. 25 MiB private R2 uploads, signature checks and PNG/JPEG preview exist; any-type 1 GiB resumable uploads, office/HEIC/GIF/video previews, malware scanning and admin file-type policy are missing.

- **NOOK-062 — Notification previews and actionable replies.** **Status: missing.** With previews at the default, mention a member whose iOS and Android devices are locked: each lock screen shows sender, conversation and message text. Turn on the org cap forcing `sender` and send again: the same event shows sender and conversation only, and the delivered payload contains no text. Turn on email text and see it in the received email; turn it off and see the next email without text. Reply from the lock-screen notification on both phones and from a desktop notification, drop the network once and retry: exactly one message posts under current membership. Remove the member from the channel and reply from a stale notification: the reply is refused with a visible failure. Mark as read from a notification and see unread, badge and the other device's notice clear. Capture the packets for a `full` notification at the NOOK-078 gateway: no message text, sender or conversation name appears.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-063 — Slack-compatible webhooks and Web API.** **Status: missing.** Repoint an unmodified GitHub Actions `slackapi/slack-github-action` incoming-webhook step and a curl `{"text","blocks","thread_ts"}` payload to a Nook webhook URL: both render with their blocks and the threaded one lands in its thread. Run an unmodified `@slack/bolt` JavaScript app and a Python `slack_sdk` script with only base URL and token changed: `chat.postMessage` then `chat.update` edits one message; signed `message` and `reaction_added` events arrive once across a forced retry; a slash command answers ephemerally and through `response_url`; a button click returns `block_actions`. The same Bolt app calls `conversations.open` for a user and `chat.postMessage` into the result: that person receives one app DM showing the app identity. It creates `#inc-123`, invites three responders, sets its topic and lists them with `conversations.members`; schedules a message with `chat.scheduleMessage` that posts once at its time; and advances a modal with `views.push` and `views.update`. The person blocks the app and the next DM is refused with `messages_tab_disabled` and posts nothing; a second app without the channel-management scope gets `missing_scope` from `conversations.create`; and no other DM or group DM is readable through either token by `conversations.history`, `users.conversations` or events. Post an unsupported block and see the text fallback, visible notice and warning. Forge a signature, replay an old timestamp, post to an owners-only channel without permission and revoke the token: each is refused with Slack's error string and no message.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-064 — Zapier, Make and n8n connectors.** **Status: missing.** In a real Zapier account, run zaps end to end: a Nook "new message in #sales" trigger appends a Google Sheets row, and a Google Forms submission runs Nook "send channel message" and "request approval"; decide the approval and see the decision trigger fire once. Repeat one trigger-plus-action scenario in Make and one workflow in n8n. A "propose commitment" action stays proposed until the assignee accepts. Revoke the grant and see the next run fail visibly with no post.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-065 — Channel-wide mentions: @channel, @here and @everyone.** **Status: partial.** In a 120-member channel with mixed choices, @channel creates Attention, push and email for every eligible member per their choices (none for the sender, muted or ignore-broadcast members; deferred for members in quiet time) and the delivered count equals 119 minus those exclusions. @here with 30 members in fresh presence reaches exactly those 30. @everyone in the default channel reaches every active non-guest and is refused in another channel. Send through the API without confirmation and receive 409 with no message; confirm and see one send. A member outside an owners-only broadcast policy, and a webhook `<!channel>` from an app without that permission, are refused with no message.

  Current evidence: `src/broadcast/audience.ts`; `src/broadcast/settings.ts`; `src/broadcast/presence.ts`; `src/platform/storage/message-statements.ts`; `src/broadcast/ConfirmBroadcast.tsx`; `tests/broadcast.mjs`; `tests/broadcast-browser.mjs`; `tests/push/broadcast.mjs`; `tests/notify/broadcast.mjs`. Web/API @channel, @here and @everyone ship with atomic saved audiences, confirmation, current-session presence/away, mandatory default-channel designation, owner/channel policy, named people, ignore/mute/quiet rules, recipient lists, email/encrypted Web Push choices and scheduled/reminder firing fences. User groups, app/webhook/workflow grants, native clients and real provider/device receipt remain unimplemented or unproven.

- **NOOK-066 — Channel posting permissions and announcement channels.** **Status: partial.** Set #announcements to owners-only posting with replies off. A member's post, thread reply, notification reply, Slack-compatible webhook post, Zapier action, workflow post and a scheduled message created before the change are all refused (the scheduled one as a visible failed occurrence), while the member still reads, reacts and saves. An owner posts; an admin override post is labelled and appears in the audit log. Open replies and see the member's thread reply accepted.

  Current evidence: `src/team/posting.server.ts`; `src/team/posting-policy.ts`; `src/team/PostingSettings.tsx`; `src/platform/storage/messages.ts`; `tests/posting.mjs`; `tests/posting-browser.mjs`; `tests/team-portability.test.mjs`. Web/API sends and edits are atomically fenced; independent thread replies, named members, labelled admin overrides and channel audit are exercised at 1440/390. Scheduled delivery now rechecks posting permission and records refusal under NOOK-034 (`src/scheduled/runner.ts`; `tests/scheduled.mjs`). User groups and their broadcast permissions remain missing; web workspace/channel broadcast policy ships under NOOK-065. The combined app/webhook/workflow/scheduler/native write-door acceptance journey remains incomplete.

- **NOOK-067 — Forwarding messages and email into conversations.** **Status: missing.** Forward a public-channel message with a note into a DM on desktop and phone and see author, source and note. Forward a private-channel message to a public channel as Link only: a public member without private access sees attribution but no body, attachment or thread, and the link refuses them; forward it as Show message and see the disclosure preview and audit entry. Set owner policy to link-only and see Show message refused. Delete the source and see each forwarded copy tombstoned. Email a PDF to a channel's address and see one attributed post; with allow-listing on, an unlisted sender is refused.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-068 — Safe link previews and app unfurls.** **Status: missing.** Paste a public article URL and see title, description and image preview with the image served from Nook; paste a YouTube and a Loom link and see their oEmbed previews. Paste links resolving to 127.0.0.1, 10.0.0.5 and 169.254.169.254 and a public URL that redirects to an internal address, and confirm through the fetch log and a listening internal server that nothing internal is contacted. An installed app with a claimed domain unfurls its own link once the author approves. The author removes a preview and it stays removed after reload on another device; an admin denies a domain and its links get no preview.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-069 — Two-factor authentication without SSO.** **Status: missing.** As owner, enforce 2FA. A member without a factor signs in by magic link and reaches only enrolment: every private API, SSR page, live socket and export is refused until they enrol with TOTP; a second member enrols a passkey on desktop and phone. A captured magic link used from another browser opens no private access without the second factor. Use a recovery code and see it audited and emailed; an admin resets a member's factors and the audit log, revoked sessions and notice show it; repeated wrong TOTP codes lock out with audit. The member opens their own sessions list, sees a phone and two browsers, signs out the phone and then all others: the phone loses private access and push at its next contact and the other browsers return to sign-in.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-070 — Polls, GIFs, thread broadcast, bookmarks and translation.** **Status: missing.** Create a named and an anonymous poll, vote from desktop and phone, close it and see the final count; a non-member cannot vote. Post a GIF through search under the rating cap, then disable GIFs as admin and see the picker gone. Send a thread reply also to the channel, edit then delete it and see both places update once. Add, reorder and remove channel bookmarks as a permitted member and be refused as a restricted one. Translate a Spanish message into English and return to the original.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-071 — Threads view and group-DM conversion.** **Status: done.** Follow three threads across two channels and a DM, receive replies and see them in the Threads view with unread counts at 1440 and 390; reply inline, mark one read and see it read on a second device; lose membership of one channel and see its thread leave the view. Convert a three-person group DM into private channel `#proj-x`: with all three still authorized, its members are those three, its full history is present and its complete original roster is retained as read-only history, the group DM is read-only with a link, an outsider cannot discover either, and the audit log shows the conversion. Repeat after one participant, including the original creator, leaves or loses access: the complete original roster remains as read-only history, but only the two currently authorized participants become members, and the converter manages the channel. Reactivate the removed participant: they still cannot read the channel or private history until an explicit channel regrant under NOOK-018. Export and restore before and after that regrant, restart, and verify the same roster, membership and access boundaries. Threads the member started, replied in or was mentioned in appear without an explicit follow (NOOK-072), and an unfollowed one leaves the view. **All unreads:** with unread messages in three conversations, ⌘⇧A lists them in sidebar order; marking one read removes it and clears it on a second device; Mark all read clears the rest and undo within ten seconds restores them; no Attention item closes.

  Current evidence: `src/chat/ThreadsView.tsx`; `src/platform/storage/threads.ts`; `src/chat/AllUnreads.tsx`; `src/platform/storage/unreads.ts`; `src/team/group-conversion.server.ts`; `tests/threads.mjs`; `tests/unreads.mjs`; `tests/group-conversion.mjs`; `tests/unreads-browser.mjs`. Web Threads, paged All unreads, cross-session reads and ten-second undo ship at 1440/390. Conversion moves full native history once and preserves its fixed original roster while granting only current authorized participants. The converter manages the private channel; an offboarded creator remains denied after reactivation until an explicit channel grant. Emitted-Worker checks validate the archive graph before/after regrant and restart. The conversation-list cap has been removed. Native clients remain NOOK-021's separate implementation.

- **NOOK-072 — Automatic thread following and channel-wide thread replies.** **Status: partial.** With every member signed in on a phone and a desktop app and not active on desktop (NOOK-073), in a `#sales` channel at the default `mentions` level, A posts a root message and B replies in its thread without mentioning A: A's phone and desktop each alert once, the thread shows in A's Threads view with one unread reply, and A's preferences list it with source `authored`. C replies once; D's later reply alerts both A and C. E is @-mentioned in the thread, then F replies, and E is alerted for F's reply. C unfollows: the next reply does not alert C; G then @-mentions C in the thread and C receives only that mention alert, and the following plain reply does not alert C; C replies again and the next reply alerts C. In a one-to-one DM, a reply in any thread alerts the other participant. With `#incidents` set to all thread replies, a reply in a thread the member never touched alerts them and appears in their Threads view, and the NOOK-032 exception list shows `#incidents`. Request `GET /api/conversations/:id/preferences` and `GET /api/threads`: the untouched live root is in `threads`, its `threadFollows` entry has `message` equal to that root ID and `source: "all"`, and its Threads item also has `source: "all"`; existing stored follows keep their sources. Repeat with only `mobileThreads: "all"`, then unfollow the untouched root and verify both endpoints exclude it. A member removed from `#sales` gets no alert and no Threads-view row for its threads. Importing a Slack history in which the member authored threads creates no follows and no alerts; their first native reply in one of those threads follows it. With the mentions-only thread badge chosen, a non-mentioning followed reply leaves the phone and desktop badges unchanged and still appears in the Threads view.

  Additional current evidence: Web all-thread mode now virtually follows untouched threads with source all, preserves sticky per-thread unfollows, respects mute/nothing, routes replies and survives archive restore (`src/platform/storage/threads.ts`; `tests/threads.mjs`; `tests/push/routing.mjs`; `tests/push/archive.mjs`). Web broadcast mentions now ship under NOOK-065 (`tests/push/broadcast.mjs`; `tests/notify/broadcast.mjs`). Web Push phone/tablet overrides and mentions-only unread/Web Push badge choice ship under the current evidence below; real native-device evidence remains pending.

  Current evidence: `src/platform/storage/threads.ts`; `src/platform/storage/thread-badge.ts`; `src/team/conversation-notify.server.ts`; `src/push/devices.ts`; `src/push/queue.ts`; `src/push/snapshot.ts`; `public/sw.js`; `tests/threads.mjs`; `tests/thread-delivery.mjs`; `tests/push-service-worker.test.mjs`; `tests/push/archive.mjs`. Broadcast audiences create atomic mentioned follows without defeating sticky unfollow. Mobile-only all-thread replies appear in Threads and route only to classified phone/tablet devices; policy changes cancel queued delivery. Mentions-only counting leaves ordinary replies visible and alerting without incrementing unread or Web Push badges. Registration initializes supported defaults once and preserves opt-outs. Notification unfollow checks the current recipient/session/ACL and reports failure; mixed-thread bursts open Threads for selection. Browser settings, persistence and populated Threads are exercised at 1440/390. Remaining: shared channels, native clients and device receipt, active-elsewhere routing, recurring quiet schedules and preview policy, under NOOK-031/021/078/073/032/062. Imported history remains inert.

- **NOOK-073 — Active-elsewhere device routing.** **Status: partial.** A member uses the macOS app with the default setting and their phone unlocked on the desk. A DM and a mention alert on the desktop only, and the phone stays silent; the device delivery view shows both held for the phone. The member reads the DM on the desktop, then locks the screen: about 1 minute later only the unread mention alerts on the phone, exactly once, and the DM is recorded as `held-active-elsewhere`. With the desktop idle for 10 minutes and unlocked, a new DM alerts the phone. Force-quit the desktop app while active: the phone alerts for a new DM within 45 seconds plus the delivery bar. Switching to "Always send to mobile, even when I'm active" makes the next DM alert both devices. With a 5-minute delay chosen, a mention after locking alerts the phone 6 minutes after the lock (1-minute lock threshold plus the delay). A call invite rings the phone while the member is active on desktop. Repeat with a focused web client in Chrome in place of the desktop app, and on Windows and Linux. A heartbeat replayed from a revoked session holds nothing. In the NOOK-021 500-event delivery-bar run with desktops active for part of the window, held events appear as `held-active-elsewhere` or are timed from release, and none is counted as displayed or silently missing.

  Current evidence: `src/push/policy.ts`; `src/push/devices.ts`; `tests/push/presence.mjs`. A fresh, session-bound visible-page heartbeat holds all of the member's Web Push and an alarm releases it at 45-second expiry; input- and lock-based desktop activity, routing by device class, release delays, "always send to mobile", call/urgent bypass, native heartbeats and `held-active-elsewhere` records are missing.

- **NOOK-074 — Native sign-in and finding the installation.** **Status: partial.** A freshly invited member opens the invitation on a laptop and scans its QR code with an iPhone that does not have the app: the App Store listing opens, and after install the app opens with the installation preselected. The member requests sign-in from the phone; the email arrives on the laptop, and typing its code into the phone signs the phone in. Reusing the code, using it after 10 minutes or typing it into a third device is refused, and 5 wrong codes lock out with an audit entry. Clicking that email's link on the laptop instead shows that the iPhone requested it, with the code, and signs the laptop browser in only after the member chooses that explicitly. On an Android phone with the app installed, tapping the magic link in Gmail opens the Nook app signed in, and no browser session is created. A member signed in on the macOS app chooses "Sign in on mobile"; the Android app scans the QR code and the desktop confirms the named phone. The phone is signed in with its own session, listed in NOOK-069 sessions as `qr-from-desktop`, and signing out the desktop leaves the phone signed in. Rescanning the same code, or scanning it after 60 seconds, is refused. With 2FA enforced, each of these paths reaches only second-factor entry or enrolment. With SSO enforced, the iOS app signs in through Okta in the system browser with PKCE, and the email-code and magic-link options are absent. Typing a mistyped installation address, or an address whose descriptor signature does not match, shows an error naming the address and connects nowhere. A Windows laptop receiving the MSI through Intune and an iPhone receiving AppConfig through the MDM both open locked to the preset installation. With Continue with Google enabled, a member whose Google address matches their confirmed mailbox signs in on the iPhone, and an unknown Google address is refused with no account created.

  Current evidence: `src/base/modules/operator-auth/identity/email-link/confirmation.mjs`; `src/team/invitations.server.ts`; `src/base/modules/operator-auth/identity/oidc/presets.mjs`; `tests/operator-auth.test.mjs`; `tests/operator-security.mjs`. Browser magic-link sign-in and invitations ship, with confirmation GET/HEAD never consuming a link and native POST consuming once; the Base OIDC module copy has Google and Microsoft presets but Nook does not wire it. Installation descriptors, open-in-app links and QR codes, managed deployment, email codes, universal and app links, QR sign-in from desktop, personal providers and system-browser native SSO are missing.

- **NOOK-075 — External participants without a Nook installation.** **Status: missing.** In our installation, invite `ana@acme.example`, whose organization runs no Nook, to the shared channel `#acme-project` and to an external DM. She confirms her mailbox with a code in the iOS app and sees only `#acme-project` and that DM, with our retention banner; our members see her with the external badge and "Acme (unverified)". She cannot browse channels, find anyone in the directory or people search, open `#vendor-print`, a default channel or any other DM, start a DM with a member she shares nothing with, create a channel or invite anyone, and each attempt is refused by the API as well as hidden in the client. `@channel` in `#acme-project` reaches her; `@here` in `#general` does not. Sharing a file labelled Confidential (NOOK-040) into `#acme-project` is blocked by DLP. She posts, and our members get the reply under their ordinary NOOK-032 levels on phone and desktop. With the policy set to require admin approval, a member's invitation waits for an admin; with it set to guests, the next invitation creates a single-channel guest instead. Remove Ana: her web, iOS and API sessions lose `#acme-project` and the DM at their next request and push stops. Invite two more Acme people, then disconnect Acme: all of them lose access on every client and API, and the audit shows each step. Later Acme runs Nook: after a mutually approved NOOK-031 connection, Ana confirms the same mailbox there and keeps the channel's full history, her authorship and the same audience.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-076 — Slack Connect cutover.** **Status: missing.** Import a Slack Pro workspace with two Slack Connect channels (`#acme-project` with 3 Acme people, `#vendor-print` with 1 vendor person whose email Slack does not supply) and one external DM with a third organization. The preview lists all three organizations, all five external people with their Slack user IDs and the missing vendor email, the external DM and each last-activity date. Choose invite for Acme and the vendor (entering the vendor's address, shown as owner-entered), and leave-in-Slack for the DM with the reason "client prefers Slack"; send at the cutover time with the Slack-side cutover message posted into both channels. An Acme person with no Nook installation confirms their mailbox and sees only `#acme-project`, with its imported history attributed to them through the Slack-user-ID mapping, the external badge on our side and our retention banner; they cannot browse channels, see our directory, or open `#vendor-print` or any DM. They post, and our members get the reply under ordinary NOOK-032 levels on phone and desktop. Removing them, or disconnecting Acme, revokes access on every client and API. The cutover report lists Acme 3 of 3 joined, the vendor 0 of 1 pending with one-action resend, and the DM as left in Slack with its reason, and the checklist closes only once every Slack Connect conversation has a disposition. A second run where a partner runs Nook invites it by installation address, and after both approve, the imported channel becomes a NOOK-031 shared channel with history intact. A message the Acme partner posts in Slack after the first import arrives with the NOOK-077 final pass, attributed through the same Slack-user-ID mapping.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-077 — Final catch-up import at cutover.** **Status: partial.** Import a Friday export of a Slack Pro test workspace, with member grants for its private channels and DMs. Over the weekend in Slack, post a new root message and a reply to an imported thread, edit one imported message, delete another, add a reaction, create a channel, start a new DM between two consenting members, add a member and create a Slack Connect channel with a partner. On Monday morning, before the delta pass, post native Nook replies in one imported thread. Run the final delta pass at the scheduled cutover time: each Slack change appears exactly once; the edit shows as a new imported revision with the earlier one in its history; the deleted message is tombstoned; the reaction, the new channel and the DM are present, and the DM is visible only to its two members; the new member appears in the invitation preview and is invited; the thread interleaves imported and native replies in time order with native ones marked; no one receives an alert, unread, Attention item or follow for imported items; and every native item is unchanged. The new Slack Connect channel appears in the NOOK-076 preview and keeps the checklist open until it has a disposition. Run the same pass again: it adds nothing. Revoke the grant covering one private channel and delete a message there in Slack: the next pass counts that channel as `unverified` with its reason and leaves the imported message intact. Force a Slack error during a scheduled final pass: the invitations wait and the owner sees the failure. The cutover report shows "imported through" the cutover time with per-pass counts, and undoing the last pass removes only its additions and revisions while the native replies remain.

  Current evidence: `src/imports/ids.mjs`; `src/imports/service.ts`; `tests/slack-import/journey.mjs`. Imported records get deterministic IDs from their Slack source identity, an interrupted import resumes, a second apply of the same upload is refused and guarded undo preserves native activity; delta passes from a later export or grants, Slack-side edits as revisions, deletion tombstones with `unverified` accounting, imported/native thread interleaving, the "imported through" report and the scheduled one-action switch are missing.

- **NOOK-078 — Push from owned installations to the store apps.** **Status: missing.** Install Nook on a fresh Cloudflare account that is not the publisher's, run setup and see the gateway registration, key fingerprint and last acknowledgement in doctor. Sign the store-published iOS and Android apps in through NOOK-074 and run NOOK-021's 500-event delivery-bar journey from that installation: it meets the bar. Capture every request the gateway receives during the run: none contains message text, a sender or conversation name, a file name or a badge count. Block the gateway for 10 minutes during the run: the affected events are recorded as `provider-unconfirmed` with reason `gateway`; the owner report, the admin health view and doctor name the gateway outage; when the block lifts, delivery resumes with no event displayed twice; and a call invite whose 30-second TTL lapsed stays `provider-unconfirmed`. Uninstall the app on one phone and see its token retired. Revoke the installation's gateway registration: pushes stop and doctor says why; re-register and they resume. Repeat a reduced 50-event journey in owner-credential mode with apps self-built and signed by the buyer's own Apple and Google accounts: setup rejects a wrong `.p8` key and accepts the right one, and a capture shows no request reaching the gateway. The published subprocessor list names the gateway with its region, availability objective, price and terms.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-054 — Scoped company-context agents and MCP.** **Status: missing.** Provision a channel agent and read-only MCP client, connect a permission-scoped document and request a summary/post. Deny access to a second private channel, an unlisted tool and a malicious source instruction; revoke membership/grants mid-run and verify no cached context or further tool write escapes. Run the official MCP Inspector against Nook's MCP server and pass its tool-listing and tool-call checks; connect two independent standard MCP clients, one authorized as a member and one as an agent, and see each return only its own permitted messages; an agent's call to an MCP server the owner has not approved is refused.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-055 — Accountable commitment assistant.** **Status: partial.** Discuss a vague request, a declined ask and an agreed ask. The assistant proposes only a cited candidate; deny author/agent acceptance on behalf of the assignee. Accept, revise a due date and close linked work: require renewed agreement and assignee completion, then pause the agent and verify no further chase or external write.

  Current evidence: `src/platform/storage/outcomes.ts`; `src/family/team-chat/attention.ts`; `tests/storage-flows.mjs`; `tests/browser.mjs`. Human proposals, exact assignee acceptance, revision and completion reports ship; agent extraction, evidence tracking and controls are missing.

- **NOOK-056 — Decisions that stay current.** **Status: partial.** Record a decision, change its linked authorized project/document to contradict it and produce a source-cited proposal for the original author. Make one source private and one stale, dismiss a false positive and revise the decision as its author; deny automatic/foreign revision and any wider audience leak.

  Current evidence: `src/platform/storage/outcomes.ts`; `src/platform/storage/outcome-history.ts`; `tests/storage-flows.mjs`. Human versioned decisions and source links ship; contradiction monitoring and proposed agent resolution are missing.

- **NOOK-057 — Calm follow-through across linked systems.** **Status: partial.** Accept a commitment linked to a PR and support case, deliver duplicate and out-of-order source events, then close/reopen one dependency and revoke another connector. Receive one calm evidence-linked update, an accurate blocked/unknown status and a proposed resolution; deny unauthorized writes and preserve assignee-only completion.

  Current evidence: `src/notify/run.ts`; `src/family/team-chat/attention.ts`; `src/platform/storage/outcomes.ts`; `tests/notify-journey.mjs`; `tests/attention.mjs`. Human obligations and calm routing ship; connected-system reconciliation, batched agent updates and external-action grants are missing.

- **NOOK-058 — Stale handoffs and proposed resolution.** **Status: missing.** Leave a handoff unaccepted, let an accepted dependency become overdue, then provide late evidence and an alternate suggested assignee. The agent separates those states, proposes a cited resolution to the permitted people, stops after resolution/pause and requires the new assignee’s own acceptance.

  Current evidence: No implementing source/test; journey pending.

- **NOOK-059 — Visible and controllable agent execution.** **Status: missing.** Start a scheduled handoff run, inspect and decline a proposed external write, interrupt the model/provider after a step, restart and revoke the grant. The owner sees a durable failed/uncertain state and exact remaining action; no duplicate write, resumed revoked access or unapproved commitment appears.

  Current evidence: No implementing source/test; journey pending.

**80 clauses: 23 done, 22 partial, 35 missing.** These counts describe source/test coverage, not a new claim that all target acceptance has run.
