Skip to content

Card view: archived sealed state + hide archived realms from write pickers#5364

Merged
lukemelia merged 6 commits into
mainfrom
cs-11670-card-view-archived-sealed-state-hide-archived-realms-from
Jun 30, 2026
Merged

Card view: archived sealed state + hide archived realms from write pickers#5364
lukemelia merged 6 commits into
mainfrom
cs-11670-card-view-archived-sealed-state-hide-archived-realms-from

Conversation

@lukemelia

Copy link
Copy Markdown
Contributor

What

Client-side handling of the realm archive seal:

  • Sealed state on direct navigation. When a realm content request returns 403 with the X-Boxel-Realm-Archived marker, 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.
  • Archived realms never appear as write targets. The three write-destination pickers (search RealmPicker, linksTo target picker, create-file destination picker) all source their realm list from the _realm-auth enumeration, 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

  • New ArchivedRealmState component (modeled on the existing card-error chrome, minus the error-detail panel).
  • stack-item.gts detects the archived case from the card error's response headers (meta.responseHeaders['x-boxel-realm-archived'] === 'true') and renders ArchivedRealmState in place of CardError.
  • create-response.ts adds X-Boxel-Realm-Archived to Access-Control-Expose-Headers so the cross-origin host can read the marker. The header is only present on the archived 403, which is only returned to authorized callers, so exposing it discloses nothing further.

Acceptance criteria

  • Navigating to an archived realm shows the sealed/archived state (driven by the 403 marker), not card chrome or a generic error.
  • Archived realms do not appear in any of the three write-destination pickers.

Testing

  • Host glint type-check + eslint + ember-template-lint clean.
  • Integration test (operator-mode-test.gts): intercepts the card fetch with a 403 + X-Boxel-Realm-Archived response and asserts the sealed state renders and a generic card error does not. The host integration/acceptance suite runs in CI.
  • Picker omission is enforced at the enumeration layer; that omission is covered by the _realm-auth server 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 clean main once they merge. Review the runtime-common/realm-server changes in their own PRs.

🤖 Generated with Claude Code

lukemelia and others added 4 commits June 29, 2026 15:01
…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>
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files      1 suites   2h 37m 33s ⏱️
3 328 tests 3 313 ✅ 15 💤 0 ❌
3 347 runs  3 332 ✅ 15 💤 0 ❌

Results for commit e5caee2.

Realm Server Test Results

    1 files      1 suites   11m 10s ⏱️
1 686 tests 1 686 ✅ 0 💤 0 ❌
1 765 runs  1 765 ✅ 0 💤 0 ❌

Results for commit e5caee2.

@lukemelia lukemelia marked this pull request as ready for review June 30, 2026 16:06
@lukemelia lukemelia requested review from a team and backspace June 30, 2026 16:07
@habdelra habdelra requested a review from Copilot June 30, 2026 16:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/host/tests/integration/components/operator-mode-test.gts Outdated
Comment thread packages/host/app/components/operator-mode/stack-item.gts
Comment thread packages/runtime-common/realm.ts Outdated
ylm and others added 2 commits June 30, 2026 12:48
- 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
@lukemelia lukemelia merged commit 46b31ea into main Jun 30, 2026
72 of 73 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants