The administrator-only Status app is registered in Platform UI and implements
the ECS, API, SendGrid, and Database views described below. It uses only
read-only GET /v6/status/* calls, lazy route/section fetching, explicit
refresh, and last-good-data retention. The cross-project design and API
contract are in
../../../../status-api-v6/IMPLEMENTATION_PLAN.md.
The Status UI ships as part of the normal Platform UI bundle. Deploying the
bundle and provisioning an optional status.<domain> alias are environment
operations outside this directory.
The local environment routes /v6/status to the Status API on port 3000. Start
status-api-v6 first, then run the normal Platform UI development server:
nvm use
yarn startAdd a standalone, administrator-only Status application to Platform UI with four tabs:
- ECS
- API
- SendGrid
- Database
The app follows Review's visual language and responsive behavior. It must use
shared libs components or status-local components; it must not import private
components from Review or Admin.
The root Platform route must contain both:
authRequired: true,
rolesRequired: [UserRole.administrator],Do not use adminReportsAccessRoles. The system-admin root grants additional
Product Manager and Talent Manager roles, which would violate the requirement
that Status is administrator-only.
The shared restricted-route role comparison is case-sensitive. Use the existing
UserRole.administrator enum value rather than a new string.
The UI guard is defense in depth and navigation control. Every API call still requires the Status API to verify the administrator JWT independently.
Use a dedicated AppSubdomain.status = 'status' and the same conditional-root
pattern as Review/Reports. This gives /status/... on the combined Platform UI
host and /... if a status.<domain> alias is provisioned later.
/status
-> /status/ecs
/ecs
/api
/api/:serviceId
/api/:serviceId/endpoints/:endpointId
/sendgrid
/database
Drill-downs are routes rather than modal-only state so browser back/forward, refresh, bookmarks, and deep links work. Server-issued IDs are opaque; the UI does not construct arbitrary resource ARNs or log groups.
src/apps/reports/src/reports-app.routes.tsxfor a standalone, subdomain-aware authenticated app.src/apps/review/src/ReviewApp.tsxfor app context/layout/outlet composition.src/apps/review/src/config/routes.config.tsfor conditional root routes.src/apps/review/src/review-app.routes.tsxfor lazy-loaded route entries.
src/apps/review/src/lib/components/Layoutfor constrained content and responsive spacing.src/apps/review/src/lib/components/NavTabsand its separate tab config for desktop/mobile navigation driven byuseLocation.src/apps/review/src/lib/components/PageWrapperfor titles, breadcrumbs, back navigation, actions, and safe external links.src/apps/review/src/lib/styles/index.scssfor neutral background, teal active state, Nunito Sans table typography, and Review table treatments.src/libs/ui/lib/components/table/Table.tsxfor declarative columns, sorting, expandable rows, clicks, androwClassName.- Review's active-review table styling as the visual reference for critical red rows and health/status pills.
Review currently imports some private Admin components. Status must not extend
that coupling. If Pagination, TableMobile, or TableLoading is genuinely reusable,
move it to src/libs/ui in a separately reviewable change with tests and
documentation; otherwise create a status-local wrapper.
StatusApp should:
- Register child routes from the platform router.
- Add/remove a status-specific body class.
- Provide only app-wide presentation/query defaults, not eager provider data.
- Render the Review-style
Layout,NavTabs, and child route outlet.
The tab config contains four always-visible entries for an already authorized administrator. Do not run a second broad role calculation that can drift from the root route.
On narrow screens, use Review's dropdown/menu treatment. The selected tab is derived from the URL and updates when navigation changes.
Implement small status-local components over libs/ui:
| Component | Purpose |
|---|---|
HealthBadge |
Critical/warning/healthy/unknown icon, label, and accessible text |
DataFreshness |
Source names, “as of” timestamp, incomplete warnings |
MetricCard |
Label, value, unit, trend/context, loading/unknown states |
StatusTable |
Shared desktop/mobile behavior and failure row class |
TimeWindowSelect |
Server-supported windows only |
RetryableErrorState |
Safe error plus Retry action |
IncompleteDataNotice |
Visible warning when API metadata is incomplete |
ExternalAwsLink |
Validated URL, new tab, noopener noreferrer |
Red must not be the only failure signal. Critical state also uses icon, badge text, row accessible label, and a visible reason.
Display a filterable service/task table. The default rows are failure-first service parents; expanding a service or switching to the task view enumerates its actual running, pending, and retained recent stopped tasks.
Service parents show:
- Severity.
- Cluster and service.
- Desired/running/pending task counts.
- Latest deployment status/time.
- Deployment counts for the last 24 hours and seven days.
- Current task-definition family/revision linked to AWS.
- Latest recent failure summary and time.
- Task/log actions.
Every task child row shows its opaque task ID, actual status/health, launch or stop time, deployment association, container state, and the task-definition family/revision taken from that task's own ARN. This matters during rolling deployments, when one service can temporarily run multiple revisions. Recent stopped tasks are paginated; the UI does not collapse the inventory to only the latest failure.
Filters:
- Text across cluster/service/task-definition.
- Cluster.
- Service and task status.
- Task-definition family/revision.
- Severity/state.
- Optional “issues only”.
Fetch the server's already failure-first list once and filter ordinary text locally. If a server filter is needed for a large catalog, debounce or require Apply; do not request on every keystroke.
The dedicated “Expanded task definition” filter applies to the lazy inventory
request and never removes service parents. This preserves access to retained
tasks running an older revision when the service's current task definition has
already advanced. When stopped-task history is warming or unavailable,
recentStoppedCount is rendered as unknown and the latest-failure cell states
that history is incomplete rather than claiming that no failures occurred.
The API owns canonical severity. The UI uses it as the primary sort and cannot place a healthy row before a critical row because a user selected another column. Secondary sorting may operate within a severity group.
Critical failure/error-redeployment rows use Review's red-row treatment. An evidenced error-driven redeployment inside the configured recent window stays red even if capacity has recovered. Warnings use a distinct warning treatment, including unexplained repeated replacements. Normal recent deployments are visible but not red unless the API supplies error/rollback/failure evidence.
An expandable row or routed drawer/page shows:
- ECS stop code and sanitized reason.
- Container and exit code.
- Generic exit interpretation explicitly labelled “generic”.
- Stopped time and source completeness.
- Task-definition and CloudWatch links.
Unknown exit codes say no generic interpretation is available; the UI never invents a cause.
Show time-window controls and summary cards for:
- Total requests.
- 2xx success ratio.
- 4xx ratio.
- 5xx ratio.
- p50 and p95 response latency.
- Unhealthy ALB targets.
Keep 3xx visible in the service table even if it is not a headline card.
The service table contains request counts, 2xx/3xx/4xx/5xx ratios, p50/p95/p99 latency, target health, and source completeness. Selecting a service navigates to its endpoint page.
The UI honors the API's dataComplete flag independently on the global,
service, and endpoint aggregates. Incomplete traffic counts, ratios, and
latencies render as unknown instead of displaying parser fallback zeroes. ALB
target health remains independently visible when its source is complete.
Group by stable method + route template. Do not display raw identifier-bearing paths as endpoint identities. Columns:
- Method and route template.
- Requests.
- 2xx/4xx/5xx ratios.
- p50/p95/p99 application/Gateway latency with the source labelled.
- Recent failure count.
Selecting an endpoint navigates to its failure page or expands a routed detail.
Show attributed-request coverage and any EDGE_UNATTRIBUTED failure count above
the table. Gateway/ALB failures that never reached application routing are
assigned only when the API's safe edge route catalog supplies a template; the
UI never derives an endpoint from a raw path. Any unattributed edge failure
makes endpoint ratios visibly incomplete.
Show at most the API-provided bounded set:
- Timestamp and request ID.
- Status code/class.
- Safe error code/type/summary.
- Response and integration/application latency with source labels.
- CloudWatch link.
Do not render raw log messages, request/response bodies, headers, query strings, source IPs, user agents, stack traces, or unknown HTML. Treat all summaries as plain text.
Show one row/card per fixed cumulative window: 15 minutes, 1, 3, 6, 12, and 24 hours.
Each shows:
- Recipient messages accepted by SendGrid after any retries.
- Recipient messages that permanently failed after retry exhaustion.
- Success/failure ratio weighted by safe numeric recipient counts.
- Accepted/failed logical send-operation counts as secondary diagnostics.
- Last terminal send time.
- Source/completeness warning.
The first release does not show a pending count: its safe aggregate source
contains terminal completion events, and the Status API does not read the email
service's PII-bearing attempt database. A provider processed state may appear
in the separately labelled recent-activity section, but it is not mixed into
the terminal acceptance ratio. Retries share one opaque send-operation ID and
recipient count, and must not double-count messages as both failed and accepted.
The UI never receives recipient addresses from this aggregate source.
Use the exact label “SendGrid API acceptance” so it is not confused with final recipient delivery.
A collapsed “Recent provider activity” section must always be available and fetch up to 50 sanitized records only when opened. It displays masked recipient, provider status, and event time; subject/body are omitted. If the provider result is capped or rate limited, display the incomplete warning and last successful refresh time.
Do not auto-refresh this section faster than the API/provider policy.
Show:
- RDS instance identifier/engine/status.
- Allocated, used, and free storage, with used percentage.
- Logical database size only when the separately approved read-only aggregate exporter is configured.
- Latest, average, and peak connection counts for the selected window.
- Recent RDS infrastructure events.
- Sanitized PostgreSQL warning/error entries and CloudWatch/RDS links.
Label the storage metric “RDS storage used” and explain that it is allocated
minus free, not a logical pg_database_size query.
The product owner must approve whether that infrastructure-storage value meets the requested “total database size” requirement. If exact logical database size is required, show the exporter-backed value separately; until it exists, render that field as incomplete rather than relabelling infrastructure usage as logical size.
Missing/stale CloudWatch samples are unknown, not zero. PostgreSQL engine logs remain visibly incomplete until export is enabled and the API says the source is complete.
Create a typed read-only status.service.ts using only xhrGetAsync with base:
`${EnvironmentConfig.API.V6}/status`Do not add a dedicated environment base unless there is a demonstrated need;
the v6 base and /status path match existing routing.
Keep:
- Wire DTOs in
models. - Pure display transforms/sorting in
utils. - Request lifecycle, stale-response suppression, and retry in hooks.
- Page layout/rendering in pages/components.
Recommended hooks:
useEcsStatususeEcsTaskDetailuseApiStatususeApiEndpointStatususeApiFailuresuseSendgridStatususeSendgridMessagesuseDatabaseStatus
Each hook runs only when its route/section is active and all IDs are ready. Review's SWR defaults (mount fetch, no focus revalidation, no polling) are a good baseline. Expose explicit Refresh/Retry and show generated/source timestamps.
Do not load all four tabs in a global context and do not add hidden polling in the initial release.
src/apps/status/
README.md
index.ts
src/
index.ts
StatusApp.tsx
status-app.routes.tsx
status-app.routes.spec.tsx
config/
routes.config.ts
lib/
components/
Layout/
NavTabs/
StatusTable/
StatusUi/
hooks/
models/
services/
status.service.ts
status.service.spec.ts
styles/
index.scss
utils/
pages/
api/
database/
ecs/
sendgrid/
Co-locate focused component/hook/utility tests with their source.
src/config/constants.tsdefinesAppSubdomain.statusandToolTitle.status.src/apps/platform/src/platform.routes.tsxregistersstatusRoutesbefore the root route.src/config/environments/local.env.tsroutes local/v6/statuscalls to port 3000.- The root
README.mdlists the hosted Status app. - Environment/global config models only if implementation proves a separate
STATUS_APIbase is required.
Platform UI deploys as one bundle; the existing CircleCI deployment should not
need a Status-specific deploy job. Add CI test execution if the repository still
does not enforce yarn test:no-watch when implementation begins.
Every page must distinguish:
- Initial loading.
- Refreshing with existing data.
- Complete empty/zero traffic.
- Partial/incomplete source.
- Stale data.
- Authorization failure.
- Provider timeout/throttling.
- General retryable failure.
Never use the same “No data” view for a complete zero and an unavailable source. Retain the last successful response during a refresh failure, mark it stale, and offer Retry.
- Keyboard-accessible tabs, filters, table rows/actions, and disclosures.
- Proper headings and page titles.
- Accessible names for icon-only refresh/external-link controls.
- Text/icon state in addition to color.
- Sufficient contrast for red/warning rows and badges.
- Desktop table and a readable mobile card/table treatment without hiding the failure reason or source completeness.
- Respect reduced-motion preferences for loading/refresh affordances.
Minimum tests:
- Root redirects to ECS.
- All child/drill routes render through the Status root.
authRequiredand exact administrator role are present.- Non-admin role does not render the app.
- Dedicated/combined host root resolution is correct.
- Every service call uses GET and
/v6/status. - Query windows/IDs are encoded and no arbitrary ARN/log group is constructed.
- Hooks do not fetch before route IDs are ready.
- Inactive tabs and collapsed SendGrid detail do not fetch.
- Stale response suppression and Retry work.
- Critical ECS rows always precede healthy rows and have non-color labels.
- Normal deployments are not falsely red.
- Loading, refreshing, complete empty, incomplete, stale, timeout, and error states render distinctly.
- Zero-request ratios render as unavailable rather than divide-by-zero values.
- Unattributed edge failures remain separate and mark endpoint coverage incomplete.
- AWS links include
target="_blank"andrel="noopener noreferrer". - API nested drill-down works across refresh/back navigation.
- SendGrid acceptance semantics and fixed windows are labelled correctly.
- Database used-storage explanation and incomplete engine-log state render.
- Responsive/accessibility behavior meets the shared UI standard.
From platform-ui, after every code change:
nvm use
yarn lint
yarn test:no-watch
yarn run buildFix every reported issue. New/changed functions, methods, and classes require
the documentation mandated by the root AGENTS.md.
- Only an authenticated
administratorcan enter any Status route. - ECS, API, SendGrid, and Database tabs exist and are responsive.
- Only the active tab reads data.
- ECS failures/error redeployments are first, red, and text/icon labelled.
- Expanded task inventory shows each task's own task-definition revision, including mixed revisions during a rolling deployment.
- Task-definition and CloudWatch links are safe and usable.
- API service and endpoint drill-down survives refresh/back/deep link.
- Response ratios and p50/p95/p99 latencies are clearly sourced.
- Recent failures show safe reasons without raw request/log data.
- All six SendGrid windows and their acceptance semantics are visible.
- Bounded, sanitized recent SendGrid provider activity loads on demand.
- Database storage, connections, RDS events, and engine warning/error state are visible.
- The approved database-size definition is shown; any required logical-size source remains explicitly incomplete until its exporter is available.
- Incomplete/stale/capped sources never appear as healthy zeroes.
- No mutation request or UI action exists.
- Status-focused tests, repository lint, and the production build pass.