Ctrl K
ComunidadGuías…

specs/admin-console.feature

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
Feature: Admin Console
  As a Realm platform administrator
  I want Console pages to manage applications, users, connectors, security, and deployment settings
  So that Realmroot can be configured from the browser

  Background:
    Given a first admin exists
    And I am signed in to Console

  @entrypoint:product-ui @journey:admin-dashboard @proof:unit
  Scenario: Admin dashboard loads tenant health
    When I open /console
    Then the dashboard shows tenant health from real management APIs

  @entrypoint:product-ui @journey:admin-signed-out-redirect @proof:unit
  Scenario: Signed-out Console routes redirect before data loads
    Given I am signed out
    When I open a Console route
    Then I am redirected to admin sign-in
    And management API data requests are not made

  @entrypoint:product-ui @journey:admin-platform-only @proof:unit
  Scenario: Organization authority does not grant Console access
    Given I am an Organization Owner without Realm platform authority
    When I open a Console route
    Then I am redirected to my Organizations page
    And Realm management API data requests are not made

  @e2e @entrypoint:product-ui @journey:organization-workspace-platform-boundary @proof:e2e
  Scenario: Organization Owners use their Workspace without Console authority
    Given I am an Organization Owner without Realm platform authority
    When I open my Organization Workspace and navigate its resource sections
    Then the Organization remains the explicit resource boundary
    When I open Console
    Then I am redirected to my Organizations page before Realm inventory loads

  @entrypoint:product-ui @journey:admin-setup-gate @proof:unit
  Scenario: Console setup gate handles missing OIDC applications
    Given no OIDC application exists
    When I open Console
    Then setup guidance is shown without blocking persistent Console routes

  @entrypoint:product-ui @journey:admin-route-backed-navigation @proof:unit
  Scenario: Console navigation exposes persistent route-backed pages
    When I use Console navigation
    Then each visible product page has a canonical route
    And the Console has no Organization context switch or context query state
    And breadcrumbs link to the Realm Console and parent collection without repeating navigation groups
    And breadcrumb labels match the actual route-backed page or selected tab
    And the current page is identified without a redundant link
    And primary Console pages use a compact page header before their navigation or data controls
    And primary inventory filters form the header of the same surface as their table
    And API documentation opens in a separate browsing context

  @entrypoint:product-ui @journey:admin-application-inventory @proof:unit
  Scenario: Applications page lists OIDC clients and status controls
    Given OIDC applications exist
    When I open the applications page
    Then clients and lifecycle controls are visible

  @entrypoint:product-ui @journey:admin-create-application @proof:unit
  Scenario: Applications page creates a typed OAuth client
    When I create an application from Console
    Then the new Application appears in inventory as confidential_web, public_spa, public_native, or machine
    And it records an explicit owner Organization
    And its Application type derives grant types, client authentication, PKCE, and OIDC scopes
    And Machine Applications receive client credentials without a redirect URI or user scopes
    And Web, SPA, and Native Applications require a redirect URI
    And the Console and Management API use the same four Application types
    And it records Resource-server-qualified scope allowlists separately from granted Permissions
    And Resource Server and scope allowlists are bounded at the request boundary
    And Public Native Applications can enable or disable device login
    And new Applications are private by default while migrated Applications remain public

  @entrypoint:product-ui @journey:admin-application-detail @proof:unit
  Scenario: Application detail manages lifecycle, redirects, integration details, and secret rotation
    Given an application exists
    When I open its detail page
    Then settings, branding, redirect URIs, integration details, and secret rotation are available
    And Resource access is visible only when the Application can act as a machine principal
    And the owner Organization is immutable after creation
    And User authorizations remain separate from Application Permissions
    And only Applications owned by the Realmroot Platform Organization can configure whether user consent is required
    And active user authorizations are read from the Application authorization subresource collection
    And revoking one removes the active authorization while preserving its audit history
    And rotating a client secret requires confirmation because the current secret stops working
    And enabling refresh tokens keeps the required offline access scope selected
    And saving authorization silently removes allowlist references to deleted Resource Servers
    And deleting it returns to inventory without refetching the removed client
    And visibility can be changed between public and private independently from OAuth client authentication

  @entrypoint:product-ui @journey:admin-create-user @proof:unit
  Scenario: Users page creates a user
    When I create a user from Console
    Then the user is persisted through the management API

  @entrypoint:product-ui @journey:admin-user-inventory @proof:unit
  Scenario: Users page supports search and status inventory
    Given users exist
    When I open the users page
    Then user search and status inventory are visible

  @entrypoint:product-ui @journey:admin-user-detail @proof:unit
  Scenario: User detail updates profile, resets password, and revokes sessions
    Given a user exists
    When I open user detail
    Then profile update, password reset, and session revocation controls work
    And direct Resource Server assignments are managed from Permissions
    And Authorized apps shows only the User's active Application authorization subresources

  @entrypoint:product-ui @journey:admin-create-connector @proof:unit
  Scenario: Connectors page creates a draft social connector
    When I create a social connector from Console
    Then the connector is saved as a draft

  @entrypoint:product-ui @journey:admin-connector-inventory @proof:unit
  Scenario: Connectors page lists email and SMS setup state
    When I open connectors
    Then Email and SMS setup state is visible

  @entrypoint:product-ui @journey:admin-social-connector-inventory @proof:unit
  Scenario: Social connectors list provider settings and availability
    When I open social connector settings
    Then provider settings and availability are visible
    And provider rows and hosted sign-in methods show a recognizable provider icon

  @entrypoint:product-ui @journey:admin-oidc-connector-inventory @proof:unit
  Scenario: Connectors page manages multiple standard OIDC clients
    Given multiple OIDC connectors are configured
    When I open connectors
    Then the existing sign-in provider inventory remains visible
    And standard page-level navigation tabs switch between built-in and OIDC connector inventories
    And each active inventory renders below the tabs in a unified data-list surface
    And inventory filters form the header of the same surface as their table
    And I can create, edit, enable for login, and delete each OIDC connector independently

  @entrypoint:product-ui @journey:admin-sign-in-settings @proof:unit
  Scenario: Sign-in settings persist registration and method availability
    When I update registration rules or hosted sign-in method availability
    Then hosted auth uses the saved availability settings
    And the active settings tab saves atomically from its inline form

  @entrypoint:product-ui @journey:admin-sign-in-experience-routes @proof:unit
  Scenario: Sign-in experience tabs use canonical Console routes
    When I navigate sign-in experience tabs
    Then the browser URL uses canonical Console routes

  @entrypoint:product-ui @journey:admin-content-settings @proof:unit
  Scenario: Hosted legal and support destinations save through the management API
    When I update hosted legal and support destinations
    Then the management API persists the Terms, Privacy, and Support URLs
    And the hosted preview footer uses them

  @entrypoint:product-ui @journey:admin-security-policy @proof:unit
  Scenario: Security pages show policy, CAPTCHA, blocklist, and general settings
    When I open security settings
    Then MFA policy, CAPTCHA, blocklist, and general settings are visible
    And the active settings tab is edited and saved inline without opening a drawer
    And session lifetimes can be managed without deployment environment variables
    And CAPTCHA can be configured with a supported provider and that provider's required credentials
    And CAPTCHA secrets are stored by the management plane without being returned to Console
    And canceling a policy editor discards every unsaved controlled value

  @entrypoint:product-ui @journey:admin-require-mfa-safely @proof:unit
  Scenario: An operator cannot require MFA before enrolling it
    Given my operator account has not enrolled MFA
    When I change the Realm MFA policy from optional to required
    Then Realmroot rejects the change with enrollment guidance
    And the current Console session remains usable

  @entrypoint:product-ui @journey:admin-create-organization @proof:unit
  Scenario: Organizations page creates an organization
    When I create an organization
    Then it appears in authorization inventory
    And the authenticated creator becomes its Owner without an owner field in the request

  @entrypoint:product-ui @journey:admin-govern-organization @proof:unit
  Scenario: Organization detail separates inventory from governance operations
    Given an organization exists
    When I select it from the Realm inventory
    Then I enter its canonical Organization Workspace
    And I can review its overview, members, Roles, Agent identities, technical resources, activity, and settings in separate routes
    And only pending invitations are counted and offered as member actions
    And the last Organization Owner cannot be demoted or removed through generic member actions
    And profile changes and lifecycle operations use a secondary management surface
    And deleting an Organization returns to inventory without refetching its removed detail
    And Realm Console retains only the cross-Organization inventory

  @entrypoint:product-ui @journey:admin-create-role @proof:unit
  Scenario: Organization Roles page creates a dynamic role
    Given I selected an Organization where my membership grants roles:write
    When I create a dynamic role
    Then it appears in authorization inventory
    And the creation form initializes it without Scope assignments
    And the Organization Role can include only assigned scopes from visible Resource Servers
    And its stable Role key cannot be changed after creation
    And another Role in the same Organization cannot reuse its key
    And predefined Roles remain readable but cannot be modified or deleted
    And an assigned dynamic Role cannot be deleted

  @entrypoint:product-ui @journey:admin-create-api-resource @proof:unit
  Scenario: Resource servers page creates a Resource server
    When I create a Resource server
    Then it appears in authorization inventory
    And it records an explicit owner Organization
    And its visibility is private by default and can be changed to public
    And I explicitly select Native or External authorization
    And Native authorization uses no Provider Connector and trusts Realmroot as the final token issuer
    And External authorization requires one Connector whose resource-authorization facet matches the advertised issuer
    And the Console reports Realmroot or the external issuer as the final token issuer
    And the authorization model cannot change after creation while an External Resource Server's compatible Connector can be replaced explicitly
    And its protected resource URL is the OAuth resource identifier and access-token audience
    And its name and description are synchronized from the OpenAPI contract and cannot be edited manually
    And OAuth scopes advertised by the business resource server protected-resource metadata remain the scope authority
    And its OpenAPI contract may add scope descriptions and maps protected operations only to advertised scopes
    And its Scopes tab manages each discovered scope's automatic or assigned grant mode
    And its Endpoints tab lists protected operations and required scope sets derived from that contract
    And external authorization connection details are included in Overview
    And Organization Roles and direct Permissions remain managed from their owning resources

  @entrypoint:product-ui @journey:admin-delete-api-resource @proof:unit
  Scenario: API resource settings soft-delete a resource
    Given an API resource exists
    When I delete the API resource from its settings
    Then the Console asks me to confirm that existing authorization will be revoked
    When I confirm the deletion
    Then the Console removes it from resource lists and details
    And the deleted resource remains only in the database for incident investigation
    And the Console offers no restoration

  @entrypoint:product-ui @journey:provider-connection-authority @proof:unit
  Scenario: One Provider Connector exposes independent authentication and resource-authorization facets
    Given a Connector driver supports authentication and resource authorization
    When I configure its Better Auth authentication client and its external authorization issuer
    Then the Console keeps both capabilities under one Provider Connector
    And the two facets use independent clients, callbacks, state, token storage, and lifecycle
    And a Resource Server can reference only the external authorization facet
    And disabling authentication does not disable its Resource Servers or existing resource connections

  @entrypoint:product-ui @journey:admin-authorization-inventory @proof:unit
  Scenario: Authorization inventory lists organizations, Organization Roles, and Resource servers
    Given authorization resources exist
    When I open the authorization pages
    Then organizations, roles, and Resource servers are listed
    And each Organization member exposes its sorted Role keys
    And replacing member Roles rejects unknown and cross-Organization Role keys
    And the last Owner cannot be removed by a Role replacement
    And each dynamic Role references only assigned scopes from visible Resource servers

  @entrypoint:product-ui @journey:admin-resource-permissions @proof:unit
  Scenario: Permissions are explicit authorization resources
    Given a visible Resource Server has assigned scopes
    When an authorized administrator grants scopes directly to a User or Application
    Then User Permissions are managed only below the target User
    And Application Permissions are managed only below the target Application
    And only Applications configured as machine principals accept Application Permissions
    And a delegated Agent administrator is recorded as the Permission grantor without impersonating a User
    And each Permission has an independent lifetime, canonical URI, and audit identity
    And Permission lists show only active records unless inactive history is requested
    And each subject exposes a searchable Authorized Resource Server collection derived from active Permissions
    And each Authorized Resource Server is a flat Resource Server summary with its active Permission count
    And assigning another scope never shortens or replaces an existing Permission
    And direct Permissions combine with optional Organization Role scopes
    But public visibility does not automatically grant any assigned scope

  @entrypoint:product-ui @journey:admin-branding-settings @proof:unit
  Scenario: Color schemes and brand assets update hosted auth
    When I choose a color scheme or update brand asset URLs
    Then the live preview updates before save
    And each Experience tab uses the standard inline form actions to discard or save its changes
    And save and discard actions remain disabled until the active tab changes
    And the custom scheme exposes only Primary, Page background, Surface, Text, and Border
    And the preview has no viewport switcher or separate open-page action
    And the preview remains fixed in the right column without a separate preview header while only the form column scrolls
    And hosted auth renders the saved branding

  @entrypoint:product-ui @journey:admin-webhook-endpoint-lifecycle @proof:unit
  Scenario: Administrators manage webhook endpoints from Console
    Given I am signed in to Console as a Realm administrator
    When I create, edit, disable, enable, rotate, and delete a webhook endpoint
    Then each endpoint change is persisted
    And each endpoint is explicitly Realm-wide or scoped to one Organization
    And Organization Workspace can list and manage only endpoints and deliveries scoped to its Organization
    And endpoint and request filters form the header of the same surface as their active table
    And invalid endpoint URLs remain actionable inside the form

  @entrypoint:product-ui @journey:webhook-event-delivery @proof:integration
  Scenario: Subscribed product events are signed, delivered, and auditable
    Given an enabled webhook endpoint subscribes to a supported product event
    When that product event occurs
    Then Realmroot posts a stable JSON event envelope to the endpoint
    And an Organization-scoped endpoint receives only events applicable to that Organization
    And the request includes an event id and event type and uses the Resource Server Application's client-credentials access token
    And every delivery attempt and bounded response is recorded as an independently addressable resource
    And large request or response bodies remain scrollable without hiding request actions
    And retrying a failed delivery creates a new signed delivery attempt under the original request

  @entrypoint:product-ui @journey:admin-deployment-settings @proof:unit
  Scenario: Deployment page shows Cloudflare runtime settings
    When I open deployment settings
    Then Cloudflare runtime configuration is visible

  @entrypoint:product-ui @journey:admin-general-settings @proof:unit
  Scenario: General Realm settings persist through the management plane
    When I update the Realm name in General settings
    Then the management API persists it on the canonical Realm resource
    And the setting is edited and saved directly in the General tab
    And hosted product surfaces use the saved Realm name
    And protocol endpoints remain derived from the canonical Realm origin

  @entrypoint:product-ui @journey:admin-email-delivery-settings @proof:unit
  Scenario: Email delivery settings persist independently from deployment variables
    Given the deployment exposes a Cloudflare Email binding
    When I configure the sender identity in Email delivery settings
    Then the management API replaces the Email delivery configuration resource
    And a stale representation retries only when the editable configuration is unchanged
    And edge delivery preserves the strong version validator used for conditional writes
    And authentication messages use the stored sender configuration
    And Console reports the binding and configuration state separately

  @entrypoint:product-ui @journey:admin-developer-access-policy @proof:unit
  Scenario: Organization creation is independent from platform Console access
    When I configure Realm developer access
    Then I can choose an Organization creation policy without changing Console access
    And Console access is displayed as restricted to Realm platform administrators
    And Organization access levels are not offered as Console access controls
    And changing an Organization access level never grants business API scopes

  @entrypoint:product-ui @journey:admin-organization-creation-policy @proof:unit
  Scenario: Realm operators control who may create Organizations
    Given Organization creation is governed independently from Console access
    When a Realm operator changes the Organization creation policy
    Then the policy can allow all users, Realm operators only, or an explicit set of users
    And every referenced user must exist before the policy is saved
    And an invalid reference leaves the previous policy unchanged
    And the policy change does not grant Console or business API authority

  @entrypoint:product-ui @journey:organization-console-resource-boundary @proof:unit
  Scenario: Organization administration uses the Organization Workspace
    Given a developer administers one Organization without Realm platform authority
    When the developer browses or manages resources in that Organization Workspace
    Then applications and API resource servers are limited to that Organization's owned inventory
    And Webhooks and audit activity are limited to that Organization
    And Organization Roles can be defined and assigned without entering Console
    And Agent identities are not part of Organization-owned inventory
    And Organization activity excludes User-owned Agent governance events
    And member inventory exposes identity details without Realm-wide authentication state
    And direct detail or mutation requests for another Organization's resources are rejected
    And Realm operators retain the complete Realm inventory in Console

  @entrypoint:product-ui @journey:admin-agent-governance-detail @proof:unit
  Scenario: Agent detail presents the stable identity governance model
    Given a stable Agent identity has bound Hosts, access requests, and Permissions
    When I open the Agent detail in Console
    Then its inventory summary uses real active Resource and scope counts
    And separate tabs show Agent installations, Permissions, audit activity, and settings
    And Resource access reads the Agent's Authorized Resource Servers and shows only the selected Resource Server's Permissions
    And each Permission reports its active or ended status separately from its end reason
    And audit activity supports searching and filtering Agent governance history
    And Agent access request history is available through audit activity instead of a separate detail tab
    And those tabs compose canonical Permission and audit collections
    And Permission collections omit history associated with deleted Resource Servers
    And protocol Agent implementation records and credential material are not exposed

  @entrypoint:product-ui @journey:admin-application-oidc-claims @proof:unit
  Scenario: Application detail exposes one platform token profile
    Given an application exists
    When I inspect or update the Application through the Console or Management API
    Then the Console exposes no per-Application OIDC claim settings
    And the Management API accepts legacy oidcClaims input without applying it and returns the fixed platform profile for migration compatibility
    And existing stored claim settings do not alter newly issued tokens

  @entrypoint:product-ui @journey:oidc-claim-emission @proof:integration
  Scenario: Applications receive standard identity and access token claims
    Given a user has organization membership, optional resource roles, and approved resource scopes
    When the Application completes an OIDC authorization flow for a Resource Server
    Then a private Application ID token identifies exactly one owner Organization in the string claim urn:realmroot:params:oauth:org
    And an authorized groups scope adds only the User's Team names from that Organization to the ID token
    And the ID token contains no Realmroot roles, permission rules, or Resource scopes
    And the access token is an RFC 9068 JWT containing client_id, audience, subject, lifetime, token identifier, and approved scope
    And the access token identifies Team names from the current Organization in groups
    And identifies effective resource roles in roles
    And carries the same string Organization context in urn:realmroot:params:oauth:org
    And no token carries the legacy object claim urn:realmroot:params:oauth:tenant
    But the access token contains no duplicate authorization object, azp, application_id, or top-level organization_id

  @entrypoint:product-ui @journey:oidc-group-application-boundary @proof:integration
  Scenario: One group-aware Application can serve multiple relying-party instances
    Given an Organization owns one public native Kubernetes Application and one confidential web Argo CD Application
    When multiple Kubernetes clusters use the native client and multiple Argo CD instances register callbacks on the web client
    Then every instance receives the same Organization-scoped Team groups for the same User
    And each relying party maps those groups to its own local authorization roles
    But Kubernetes and Argo CD do not share an Application or client secret boundary

  @entrypoint:product-ui @journey:agent-discovery @proof:unit
  Scenario: AgentAuth discovery exposes a narrow delegated protocol surface
    When an agent client requests /.well-known/agent-configuration
    Then Realmroot advertises delegated mode and device authorization approval
    And AgentAuth advertises no Resource API capabilities
    And the advertised endpoints, issuer, and proof algorithms are authoritative for the client
    And Management API authority is expressed only as OAuth scopes

  @entrypoint:product-ui @journey:admin-agent-inventory @proof:unit
  Scenario: Admins govern Agents without managing protocol internals
    Given delegated AgentAuth hosts, Agents, Permissions, and approval requests exist
    When Console reads the tenant Agent inventory
    Then Realmroot presents stable Agents, access requests, Permissions, account connections, and audit events
    And large Agent inventories can be traversed one bounded server page at a time
    And it does not expose hosts, registrations, bindings, or protocol approval records as management resources
    When an admin deletes an Agent or revokes a Permission
    Then the Agent or Permission is no longer active
    And no autonomous agent mode or broad admin mutation capability is enabled

  @entrypoint:restish @journey:site-settings-migration @proof:unit
  Scenario: Existing site configuration survives unified settings migration
    Given existing sign-in, branding, account-center, email and security configuration
    When site settings storage is migrated
    Then all configured values and nulls are preserved in named settings groups
    And old configuration tables remain until the new release is verified

  @entrypoint:restish @journey:site-settings-concurrency @proof:integration
  Scenario: Concurrent site settings changes preserve independent groups
    When administrators update different site settings groups
    Then both updates persist
    And a stale revision cannot overwrite a newer group revision

  @entrypoint:product-ui @journey:site-navigation-settings @proof:integration
  Scenario: Operators configure optional external service navigation
    When a platform operator saves ordered external service links
    Then public configuration exposes the saved links
    And invalid destinations and unauthorized writes are rejected

  @e2e @entrypoint:product-ui @journey:site-navigation-console @proof:e2e
  Scenario: Operators manage service links and users navigate to them
    Given an operator opens Settings from the Console sidebar
    And General settings contains neither external services nor account-permission controls
    When the operator opens the External services tab
    Then the URL identifies the External services settings page
    When the operator adds, edits and reorders service links in dialogs
    Then Account Center shows the saved links in desktop and mobile navigation
    And removing all links hides the external service group

  @entrypoint:restish @journey:site-settings-cleanup @proof:unit
  Scenario: Verified site settings retire legacy storage
    Given existing configuration has been migrated and the new release verified
    When legacy settings storage is removed
    Then the current settings and revisions remain unchanged
    And the old settings tables and temporary synchronization triggers no longer exist
    And cleanup refuses to discard configuration that has no migrated group