Card view: archived sealed state + hide archived realms from write pickers#5364
Merged
lukemelia merged 6 commits intoJun 30, 2026
Conversation
…archived-for-all-content-requests' into cs-11670-card-view-archived-sealed-state-hide-archived-realms-from
…ved-realms-from-_realm-auth-realm' into cs-11670-card-view-archived-sealed-state-hide-archived-realms-from
…archived-for-all-content-requests' into cs-11670-card-view-archived-sealed-state-hide-archived-realms-from
When a realm content request comes back 403 with the X-Boxel-Realm-Archived marker, stack-item renders a dedicated archived state (a locked "Workspace Archived" header plus a restore-from-the-chooser message) instead of card chrome or a generic card error. Detection reads the marker from the card error's response headers. The three write-destination pickers (search RealmPicker, linksTo target picker, create-file destination picker) need no change: all source their realm list from the _realm-auth enumeration, which omits archived realms, so archived realms never appear as write targets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an “archived/sealed realm” flow end-to-end: the realm runtime returns a dedicated 403 marker for archived realms, and the host UI renders a purpose-built sealed state instead of generic card error chrome; archived realms are also omitted from the realm enumeration used by write-destination pickers.
Changes:
- Introduces an archived-realm seal at the realm request boundary (403 +
X-Boxel-Realm-Archived, plus a stable JSON:API error code). - Updates realm permission enumeration to exclude archived realms by default (with an opt-in to include them).
- Adds host UI + test coverage for rendering a sealed “Workspace Archived” state on direct navigation.
Key review notes:
- The host’s archived-marker detection should treat response header names as case-insensitive (consistent with other header handling).
- New test prose should avoid private tracker identifiers.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/runtime-common/router.ts | Adds an ArchivedRealmError type for the archived/sealed realm boundary. |
| packages/runtime-common/realm.ts | Enforces the archived seal after authorization and returns a marked 403 response. |
| packages/runtime-common/db-queries/realm-permission-queries.ts | Excludes archived realms from permission enumeration by default; adds includeArchived opt-in. |
| packages/runtime-common/create-response.ts | Exposes X-Boxel-Realm-Archived via CORS so the host can read it cross-origin. |
| packages/realm-server/tests/realm-endpoints/archived-seal-test.ts | Adds server-side tests for sealed behavior, readiness exemption, and non-disclosure to unauthorized callers. |
| packages/realm-server/tests/realm-auth-test.ts | Verifies /_realm-auth omits archived realms and re-includes after unarchive. |
| packages/realm-server/tests/queries-test.ts | Adds query tests for default archived exclusion and includeArchived behavior. |
| packages/realm-server/tests/index.ts | Registers the new archived seal test file. |
| packages/host/tests/integration/components/operator-mode-test.gts | Adds an integration test asserting the sealed UI state renders on the archived marker. |
| packages/host/app/components/operator-mode/stack-item.gts | Detects archived-marker 403s via response headers and swaps in ArchivedRealmState. |
| packages/host/app/components/operator-mode/archived-realm-state.gts | New template-only sealed/archived UI state component. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- operator-mode-test: drop the private tracker reference from the new test's comment; the marker behavior is self-evident from the request body the test mounts. - realm.ts: the archived-realm seal exempts everything in #publicEndpoints (`POST /_session` and `GET /_readiness-check`), not readiness only. Reword the comment to match the actual lookup. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…chived-sealed-state-hide-archived-realms-from # Conflicts: # packages/runtime-common/realm.ts
habdelra
approved these changes
Jun 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Client-side handling of the realm archive seal:
403with theX-Boxel-Realm-Archivedmarker, the stack item renders a dedicated archived state — a locked "Workspace Archived" header plus a "restore it from the workspace chooser, or ask an owner to restore it" message — instead of card chrome or a generic card error. There is no read-only browsing; an archived realm is sealed for everyone.linksTotarget picker, create-file destination picker) all source their realm list from the_realm-authenumeration, which omits archived realms. No picker code change is needed — verified by tracing each path; none has an independent realm source that would re-include an archived realm.How
ArchivedRealmStatecomponent (modeled on the existing card-error chrome, minus the error-detail panel).stack-item.gtsdetects the archived case from the card error's response headers (meta.responseHeaders['x-boxel-realm-archived'] === 'true') and rendersArchivedRealmStatein place ofCardError.create-response.tsaddsX-Boxel-Realm-ArchivedtoAccess-Control-Expose-Headersso the cross-origin host can read the marker. The header is only present on the archived403, which is only returned to authorized callers, so exposing it discloses nothing further.Acceptance criteria
403marker), not card chrome or a generic error.Testing
operator-mode-test.gts): intercepts the card fetch with a403+X-Boxel-Realm-Archivedresponse and asserts the sealed state renders and a generic card error does not. The host integration/acceptance suite runs in CI._realm-authserver tests.Dependencies (stacked)
Built on the sealed-403 enforcement and the archived-omitting enumeration. The diff includes those changes until they land on
main; I'll rebase onto cleanmainonce they merge. Review the runtime-common/realm-server changes in their own PRs.🤖 Generated with Claude Code