CONTEXT_limited_mode.md
Limited Mode (Web) — Project Context
Purpose
This context document captures the current design and implementation context for Limited Mode in the web UI.
Primary goal: allow non-admin users to access a strictly scoped subset of tenancy analysis data, while ensuring backend enforcement prevents data disclosure through direct API payload tampering.
This is a project/context artifact (architecture + behavior + acceptance), not a task-focused end-user quickstart.
Problem Statement
Original web auth was effectively binary (authenticated vs not authenticated), without explicit modeling for:
role (
adminvslimited)compartment scope
identity-domain scope
This allowed authenticated users to reach broad data surfaces once tenancy data was loaded.
Limited Mode introduces tenancy-bound limited keys and mandatory server-side scoping to enforce least privilege.
Business Rules (Current)
Limited profiles are per tenancy.
Limited users are scoped to a compartment root path (including descendants).
Limited users may have an allow-list of identity domains.
Empty allowed identity domains means no IAM detail access:
users / groups / dynamic groups should return empty sets.
Policy statement text may still contain principal names.
Limited users must not access admin/index/load/cache surfaces.
Simulation is available for limited users only when
policy_scope_mode=include_relevant_ancestors.Prospective statements are view-only for limited users:
no create/edit/replace/validate/builder access
only scoped prospective rows are visible
Security Model
Roles
Admin
Authenticated with runtime admin key.
Can load/cache tenancy data, manage limited profiles, and use full surfaces.
Limited
Authenticated using an activated limited key mapped to a profile.
Access restricted to scoped analysis pages.
Session Contract (Target)
{
"authenticated": true,
"auth_mode": "limited",
"auth_key_fp": "...",
"limited_scope": {
"profile_id": "...",
"tenancy_ocid": "ocid1.tenancy...",
"compartment_root_paths": ["ROOT/Finance"],
"policy_scope_mode": "strict_descendants",
"allowed_identity_domains": ["Default", "CorpDomainA"]
}
}
Key Storage Rules
Never persist plaintext limited keys.
Persist key hash/fingerprint only (e.g., SHA-256).
Newly generated key material is shown once at creation/activation time.
Runtime Activation Lifecycle
Profile definitions may persist, but limited keys are runtime-scoped credentials:
Admin activates/generates limited keys during an admin session.
Activated limited keys are valid only for current process runtime.
Restart clears active limited keys by default.
Admin must re-activate/re-generate after restart.
This mirrors runtime admin-key behavior and reduces long-lived credential exposure.
Phase-1 Operational Decisions
Existing admin startup runtime key logging remains unchanged.
Limited profile definitions persist under tenancy settings.
Runtime activation state is non-persistent (inactive at startup).
Admin utility controls include:
activate limited profile key
deactivate limited profile key
display active key material in admin utility view
While profile key is active, scope criteria controls are read-only in UI.
When inactive, scope criteria become editable.
UX Requirements (First Pass)
Admin Utility Surface (Limited Scope Management)
Admin-only page/section with at least:
list limited profiles for current loaded tenancy
create/edit profile label, compartment root, allowed identity domains
activate/generate runtime limited key (display once)
deactivate runtime key(s)
enable/disable profile definition
Visibility rules:
visible only to admin sessions
hidden/blocked for limited sessions
excluded from limited-mode navigation
Limited Landing Experience
On limited login, route to a simplified landing card indicating:
scoped-data banner
tenancy context
scoped compartment root (descendants included)
allowed identity domains (or explicit none)
full admin/simulation/full-data unavailable warning
instruction to contact admins for broader scope
Masthead
Display app version plus role badge:
AdminLimited
API Enforcement Strategy (Critical)
Enforcement is backend-side on every relevant route; UI hiding is not security.
Core Predicates
For limited sessions, returned records must satisfy:
Compartment predicate: effective/policy path within scoped subtree.
Domain predicate (IAM detail only): entity domain in allow-list.
First-Pass Route Matrix
Route |
Limited behavior |
|---|---|
|
Return statements only within scoped subtree |
|
Same compartment scoping; expansions remain scoped |
|
Allowed domains only; empty if domain list empty |
|
Allowed domains only; empty if domain list empty |
|
Allowed domains only; empty if domain list empty |
Resource-principal analysis routes |
Apply compartment subtree scoping |
Admin/load/cache routes |
Deny (403) for limited |
|
Allowed only when |
|
Same as above; compartment/domain scope enforced |
|
Same as above |
|
Same as above; compartment/domain scope enforced |
|
Same as above |
|
Same as above; returns scoped prospective-only rows |
|
Limited users: scoped read-only rows only |
|
Admin-only |
|
Admin-only |
Policy Visibility Mode
Limited profiles include policy visibility mode:
policy_scope_mode: "strict_descendants" | "include_relevant_ancestors"
Semantics:
strict_descendants(default)include scoped root and descendants only
include_relevant_ancestorsalso include relevant ancestor-scope statements affecting scoped subtree
This applies to policy statement visibility only; IAM detail visibility remains
controlled by allowed_identity_domains.
Anti-Tamper Requirement
If limited users craft broadened API payloads, backend must still:
enforce scope
ignore out-of-scope expansions
return only scoped rows (or empty)
Data Model (Limited Profiles)
Legacy-style persisted shape
{
"limited_access_profiles": [
{
"profile_id": "uuid",
"label": "Finance auditors",
"enabled": true,
"tenancy_ocid_hash": "sha256(...)",
"compartment_root_path": "ROOT/Finance",
"allowed_identity_domains": ["Default"],
"key_hash": "sha256(limited_key)",
"created_at": "ISO8601",
"updated_at": "ISO8601"
}
]
}
Preferred tenancy-keyed persistence
{
"limited_access_by_tenancy": {
"ocid1.tenancy.oc1..aaaa...": {
"profiles": [
{
"profile_id": "uuid",
"label": "Finance auditors",
"enabled": true,
"compartment_root_path": "ROOT/Finance",
"policy_scope_mode": "strict_descendants",
"allowed_identity_domains": ["Default"],
"created_at": "ISO8601",
"updated_at": "ISO8601"
}
]
}
}
}
Notes:
Persistence should be tenancy-keyed (tenancy OCID preferred).
tenancy_ocid_hashprotects against wrong-tenancy key usage.allowed_identity_domains: []is valid and means no IAM detail visibility.Runtime key activation state is non-persistent and references profile IDs.
Implementation Phases
Phase 1 (Current Scope)
Role-aware session model (
admin/limited).Limited profile CRUD backend + admin management page.
Limited login resolving profile + scope.
Server-side scope guards on first-pass endpoints.
Limited landing card + role badge + nav restrictions.
Hard blocks for admin/load/cache in limited mode.
Conditional simulation access for limited mode when
policy_scope_mode=include_relevant_ancestors.Prospective statements read-only visibility for limited mode across Policy Analysis and Simulation.
Phase 2 (Future)
Extended reporting under scope.
Key expiration/rotation automation.
Acceptance Criteria (Phase 1)
Admin can create limited profile (key, compartment root, domain allow-list).
Limited key login yields limited scoped session + landing experience.
Limited users cannot access admin/index/load/cache routes.
Limited users can access simulation routes only when
policy_scope_mode=include_relevant_ancestors.Limited users have no prospective mutation capabilities; scoped prospective visibility is read-only.
Policy/analysis outputs are scope-limited.
Empty domain allow-list produces zero IAM detail rows.
Crafted API payloads cannot reveal out-of-scope data.
Test Checklist
Create limited profile with non-root compartment + one allowed domain.
Login with limited key; verify role badge + scope warning card.
Verify allowed pages work; blocked pages return 403/redirect.
Verify simulation is enabled only for
include_relevant_ancestorsprofiles.Verify policy routes exclude statements above scope root.
Verify users/groups/dynamic-groups restricted to allowed domains.
Verify empty-domain profile returns empty IAM endpoint results.
Verify limited users can only view (not edit/build/replace) prospective statements.
Attempt API payload tampering; verify scoped-only outputs.
Risks / Notes
Scope filtering should be centralized to avoid route drift.
UI should clearly signal that empty results may be scope-driven.
Simulation is conditionally enabled; route guard drift would be a leak vector, so
_require_simulation_accessmust remain the single enforcement gate.