Application Details and Actions — SPEC

Start here → AGENTS.md · SPEC_INDEX.md · ARCHITECTURE.md.

Metadata

FieldValue
Module idapplication-details-and-actions
Source path(s)src/pages/applications/, app-detail/action components, action API routes, src/lib/add-bot-*.ts
Doc kindModule spec
Coverage score100% assessed 2026-07-24; 14/14 mandatory fields PRESENT, existing detail-route found/not-found evidence verified
Generated frommodule-spec @ 0.2.1
generated_by / approved_by / updated_atcodex (gpt-5.6) / repository owner scope approval / 2026-07-24
Validation statuspass-with-warnings; validator claude-opus-4-8-1m (runtime independent of codex), target HEAD b9c7321ee3642bdb0137734e187a102a7f5de9be, assessed 2026-07-24; 0 Blocking, 0 Important, 0 Medium, 2 Minor; full suite environment-blocked (Node 24 + registry pending)

Evidence Rules

The app detail page, URL/analytics helpers, action APIs, stores/components, and tests define current behavior. The earlier add-bot plan was verified against this implementation.

Source Material Register

Source materialScopeDecisionDisposition
Add Bot flow specificationUI/API/state/analyticsverified/correctedCurrent modal, auth, rooms, membership/message actions and analytics
Current page/helpers/testsdetail/actionsauthoritativeRequirements, flow, failures, tests

Overview

/applications/[appId] server-renders normalized application detail content and conditionally exposes actions such as bot addition, messaging, native integration connection, authorization removal, webhooks, embedded app access, and external links. React/Astro components use same-origin action APIs and concern-specific stores.

Purpose / Responsibility

Owns application-detail presentation and user actions tied to one catalog application; data source normalization, global auth, and webhook persistence remain elsewhere.

Stack

Astro dynamic page, Astro/React components, Nano Stores, same-origin APIs, adapter helpers, Vitest.

Folder / Package Structure

src/pages/applications/[appId].astro
src/components/
├── AppDetailsHero.astro
├── AppDetailsDescription.astro
├── AddBotModal.astro
├── EmbeddedAppModal.astro
└── RequiresAdminModal.astro
src/pages/api/{auth-status,check-authorization,rooms,create-membership,send-direct-message,validate-embedded-app-access}.ts

Key Files (source of truth)

FileHolds
src/pages/applications/[appId].astroSSR lookup, page composition, action gating
src/lib/app-details-urls.tssafe/detail action URL construction
src/lib/add-bot-urls.tsadd-bot route/body helpers
src/lib/add-bot-analytics.tsevent construction
action API route filesauth, validation, upstream mutation
src/stores/appDetailsStore.ts, roomsStore.tsbrowser state

Public Surface

Contract IDTypeSurfacePurposeCompatibilityDetailRoot
application.detailHTTPGET /applications/:appIdRender detail pageURL/metadata/action stabilitypage fileCONTRACTS.md
application.auth-statusHTTPauth/authorization check APIsGate actionsadditive JSONAPI filesCONTRACTS.md
application.add-botHTTProoms/membership/message APIsComplete bot flowbody/status stableAPI filesCONTRACTS.md
application.embedded-accessHTTPembedded access APIGate embedded launchreason/status stableAPI fileCONTRACTS.md

Requires (dependencies)

Synchronized app lookup, auth/session, Webex/Hydra APIs, media helpers, stores/notifications, URL safety, analytics, middleware/CSRF.

Requirements

IDWHATWHYSource EvidenceTest EvidenceGapsConfidence
APP-R-001Detail route MUST validate/resolve appId, render current normalized data with canonical SEO, and return current not-found behavior when absent.Keeps direct URLs SSR-complete and safe.src/pages/applications/[appId].astro, src/lib/fetch-synced-data.ts, src/lib/seo.tsplaywright/tests/functional/apps/app-detail.spec.ts, tests/unit/lib/listing-app.test.ts, tests/unit/lib/seo.test.tsnonePRESENT
APP-R-002Action visibility/URLs MUST derive from normalized app type/capabilities and centralized helpers, not arbitrary CMS strings.Prevents unsafe/inconsistent actions.src/components/AppDetailsHero.astro, src/lib/app-details-urls.ts, src/lib/add-bot-urls.tstests/unit/lib/app-details-urls.test.ts, tests/unit/lib/add-bot-urls.test.tsnonePRESENT
APP-R-003Add Bot MUST require authentication, load rooms, validate room/message inputs, create membership or direct message through same-origin protected APIs, and report success/failure.Completes the user action without exposing tokens or false success.src/components/AddBotModal.astro, src/pages/api/rooms.ts, src/pages/api/create-membership.ts, src/pages/api/send-direct-message.tstests/unit/lib/api-bot.test.ts, tests/unit/stores/roomsStore.test.tsfull live E2E externalPRESENT
APP-R-004Embedded app access MUST evaluate server-side user/app policy and fail closed on configured service/token errors.Prevents unauthorized launch.src/pages/api/validate-embedded-app-access.ts, src/components/EmbeddedAppModal.astrotests/unit/lib/api-validate-embedded-app-access.test.tsexternal policy integrationPRESENT
APP-R-005Analytics MUST use centralized event/property builders and must not include credentials or sensitive session data.Preserves telemetry compatibility and privacy.src/lib/add-bot-analytics.ts, src/lib/analytics.tstests/unit/lib/add-bot-analytics.test.ts, tests/unit/lib/analytics.test.tsend-to-end delivery externalPRESENT

Design Overview

The page is SSR-first. Normalized application data selects component variants and action affordances. Complex action flows hydrate only their islands/stores. All protected calls go through App Hub APIs, which apply session/CSRF/input controls and proxy to upstream clients.

Data Flow

flowchart LR
  URL --> DetailPage --> SyncRead["Redis/sync lookup"]
  SyncRead --> View["SSR detail components"]
  View --> Action["React/modal action"]
  Action --> Store
  Action --> LocalAPI
  LocalAPI --> Auth --> Webex

Sequence Diagram(s)

Operation groupDiagramFailure coverage
Detail renderID → data → SSRinvalid/missing application
Add botauth → rooms → membership/messageunauthenticated, invalid input, upstream error
Embedded launchaccess evaluation → modal/navigationnot configured, token/fetch denial
sequenceDiagram
  participant U as User
  participant D as Detail UI
  participant A as App Hub API
  participant W as Webex
  U->>D: Add bot
  D->>A: GET rooms
  A->>W: authorized rooms
  W-->>A: rooms
  A-->>D: items
  U->>D: choose room / direct message
  D->>A: protected POST
  alt success
    A->>W: membership/message
    W-->>D: success
  else failure
    A-->>D: stable error
  end
sequenceDiagram
  participant B as Browser
  participant P as Detail page
  participant R as Synchronized catalog
  B->>P: GET /applications/:appId
  P->>P: validate identifier
  P->>R: lookup friendly/raw id
  alt found
    R-->>P: normalized application
    P-->>B: SSR detail + canonical metadata/actions
  else missing
    R-->>P: null
    P-->>B: current not-found response
  end
sequenceDiagram
  participant U as User
  participant M as Embedded app modal
  participant A as Access API
  participant S as Settings service
  U->>M: request launch
  M->>A: GET access for app id
  A->>A: session/token/app validation
  opt configured authenticated policy
    A->>S: evaluate user access
  end
  alt allowed
    A-->>M: allowed true
    M-->>U: launch
  else denied/error
    A-->>M: allowed false + reason
    M-->>U: remain closed/error
  end

Class / Component Relationships

classDiagram
  class DetailPage
  class DetailComponents
  class ActionModal
  class AppDetailsStore
  class RoomsStore
  class ApiRoutes
  DetailPage --> DetailComponents
  DetailComponents --> ActionModal
  ActionModal --> AppDetailsStore
  ActionModal --> RoomsStore
  ActionModal --> ApiRoutes

Use Cases

State Model

appDetailsStore holds current app/loading/error/embedded-access; roomsStore holds room list, membership and direct-message action errors. Modal visibility is coordinated by modal/client scripts and store state where applicable.

Business Rules & Invariants

Concurrency & Reactive Flow

State Machine

stateDiagram-v2
  [*] --> SSRReady
  SSRReady --> AuthRequired: protected action unauthenticated
  SSRReady --> LoadingAction: valid action
  LoadingAction --> Success: upstream success
  LoadingAction --> Error: validation/upstream failure
  AuthRequired --> SSRReady: login complete
  Error --> LoadingAction: retry
  Success --> SSRReady: dismiss

UI Flow

Error Handling & Failure Modes

ConditionSignalRecovery
Unknown app404/not-foundcorrect URL
Unauthenticated actionlogin/auth-required UIlogin then retry
Invalid room/message/app ID400 browser-safe errorcorrect input
Upstream rejectionmapped error/notificationinspect permission, retry
Embedded access denied{allowed:false, reason}do not launch

Pitfalls

Module Do’s / Don’ts

Key Design Trade-off

SSR detail pages maximize direct-navigation/SEO reliability, while selectively hydrated action flows add coordination complexity across components, stores, and protected APIs.

Test-Case Strategy (module)

Test URL/analytics helpers, auth/action API validation and status mapping, store transitions, modal/component states, SSR build, and authenticated E2E where service test users are available.

BehaviorEvidenceGap
detail route found/not-foundplaywright/tests/functional/apps/app-detail.spec.tsnone
URL/analyticsadd-bot/app-detail helper testsnone
action APIsAPI bot/auth/embedded testslive upstream
stores/UIrooms/appDetails/component testsfull journey environment-dependent

Traceability