Spike: Introducing Case-Level Visibility
Summary
This spike proposes a safe, incremental way to introduce a new, simplified access model.
The goal is to introduce case‑level visibility and user‑level permissions in a way that:
- avoids risky client migrations
- allows us to test the new model in production ourselves
- Preserves existing behaviour for all current customers
The approach relies on:
- an organisation‑level feature flag
- a strict v2 / v3 API boundary
- incremental rollout of new permissions starting from current defaults
Core constraints and principles
Design principles
- No after‑the‑fact customer migrations
- No behaviour changes for existing organisations
- Workspace scoping remains the foundation of all data access during development and testing
- Default new data structures to match current production
Current production behaviour
Today, effective visibility behaves as:
- Access is always scoped to the workspace
- Within a workspace, all users can see all cases
- Assets inherit visibility from the workspace
This baseline becomes the default mode for the new system.
Target simplified permission model (v3)
Roles
- Admin
- User
Admins:
- Can view and edit all cases within the current workspace
Users:
- Visibility is controlled at the case level
Case‑level visibility modes
Each case has an explicit visibility setting:
-
Workspace‑wide
All workspace users can view/edit
(default; matches current production behaviour) -
Named users
Only explicitly selected users can view/edit
Assets always inherit visibility from their case.
Testing case visibility in parallel
Organisation‑level flag
Introduce a new "feature flag" field on the organisation model, for example:
case_visibility_enabled bool (default: False)
API
Current state (v1/v2 relevant paths)
Current FE API calls
- Asset listing Page
- Asset Detail
- Custom Tracker Asset Form
- Self-Hosted Asset Form
- Generated Asset Form
- Tangible Asset Form
- Asset Seizure Selector
- Activity Component (transactions)
- Seizure Asset Wizard
- Wrapped Assets Hook
- Wrapped Operation Assets Hook
Assets are accessible in two ways:
Global assets
/assets/assets/{id}/assets/digital/assets/physical/assets/{id}/transactions/assets/{id}/refresh/assets/{id}/archive/assets/{id}/restore
Operation-scoped assets
/operations/{id}/assets/digital/operations/{id}/assets/physical
Generated client hooks in use on the frontend
useGetAssetsDigitaluseGetAssetsPhysicaluseGetAssetsIdusePostAssetsusePutAssetsIduseGetAssetsIdTransactionsusePostAssetsIdRefreshuseGetOperationsIdAssetsDigitaluseGetOperationsIdAssetsPhysical
v2 APIs (legacy)
- Preserve all existing semantics
- No behavioural changes, e2e tests are not changed
- Continue to serve all organisations
v3 API
Rules
- Designed specifically for case‑level visibility
- Use consistent scoping and PATCH semantics
- Assets are always scoped to an operation
- Adds a joint /assets endpoint which returns all asset types
- Retains the /digital and /physical endpoints for backwards compatibility
- Workspace context is implicit via session
Proposed v3 hook mapping
| Capability | v1 / v2 | v3 |
|---|---|---|
| List specific asset types | GET /operations/{id}/assets/digitalGET /operations/{id}/assets/physical | GET /v3/operations/{operationId}/assets |
| List all asset types | GET /assets | GET /v3/operations/{operationId}/assets |
| Create asset | POST /assets | POST /v3/operations/{operationId}/assets |
| Update asset | PUT /assets/{id} | PATCH /v3/operations/{operationId}/assets/{assetId} |
| Asset detail | GET /assets/{id} | GET /v3/operations/{operationId}/assets/{assetId} |
| Transactions | GET /assets/{id}/transactions | GET /v3/operations/{operationId}/assets/{assetId}/transactions |
| Refresh | POST /assets/{id}/refresh | POST /v3/operations/{operationId}/assets/{assetId}/refresh |
| Archive / restore | POST /assets/{id}/archive/restore | POST /v3/operations/{operationId}/assets/{assetId}/archive/restore |
v3 Endpoints
GET /v3/operations/{operationId}/assets (physical & digital)
POST /v3/operations/{operationId}/assets
GET /v3/operations/{operationId}/assets/{assetId}
PATCH /v3/operations/{operationId}/assets/{assetId}
GET /v3/operations/{operationId}/assets/digital
GET /v3/operations/{operationId}/assets/physical
GET /v3/operations/{operationId}/assets/{assetId}/transactions
POST /v3/operations/{operationId}/assets/{assetId}/refresh
POST /v3/operations/{operationId}/assets/{assetId}/archive
POST /v3/operations/{operationId}/assets/{assetId}/restore
Rollout
Phase 1
- Add organisation‑level feature flag
- Add organisation-level case visibility default
- Add case permission fields, defaulted to organisation default
- Disable the existing asset transfer mechanism
- Implement v3 read paths
- Enable the flag for internal organisations only
Phase 2
- Introduce v3 write endpoints for case visibility
- Allow patching cases to "named users" / "workspaces"
- Expand v3 asset creation/update flows
Phase 3
- Test real production usage internally
- Identify edge cases and performance impacts
Phase 4
- Toggle the feature for existing orgs, as needed.
Testing strategy
Aims
- v2 e2e tests remain unchanged
- v3 has its own dedicated e2e test suite
Key flows to test
- Workspace‑wide default behaves identically to legacy
- User loses access immediately when removed from a case
- Assets are inaccessible once case visibility is revoked
- Admin always has full access within the workspace
- No cross‑operation or cross‑workspace leakage