Skip to content

OnePlatform User Story Analysis v2

Date: 2026-06-13 Method: 6-perspective automated analysis Previous analysis: USER-STORIES-ANALYSIS.md (108 friction points) This analysis: 202 raw findings across 6 perspectives, deduplicated to 85 unique findings


Summary Table

Severity Count
CRITICAL 13
HIGH 35
MEDIUM 31
LOW 6
Total unique findings 85

Methodology

This analysis applies six distinct user perspectives to the OnePlatform codebase simultaneously. Each perspective produces a set of findings from its vantage point. Raw findings are then deduplicated — when multiple perspectives flag the same root cause, they are merged into a single finding with all contributing perspectives noted. This approach surfaces both technical defects visible only to specialists (security reviewers, ops engineers) and experiential failures visible only to end users.

Perspectives Applied

Perspective Focus Area
data-engineer Connector setup, ingestion pipelines, ontology mapping, scheduler wiring
app-developer SDK ergonomics, BFF hooks, type accuracy, build/deploy lifecycle
plugin-author Plugin scaffold quality, pack/publish flow, simulation tooling, GPG verification
ops-admin Docker Compose completeness, secret hygiene, logging, resource limits, TLS
new-user First-run experience, routing, onboarding UI, error messages, documentation gaps
security-reviewer Auth flows, header injection, scope coverage, encryption, container hardening

Top 10 Priorities

These findings represent the highest-impact, most actionable items. Several are single-line or two-line fixes with outsized consequences.

# Finding Severity Why It Matters Effort
1 Strip X-User-Context header in gateway proxy CRITICAL Enables full impersonation via header injection — any external caller can set their own identity Single-line fix in HEADERS_TO_STRIP set
2 Generate real passwords for Postgres/Redis/PgBouncer in init.sh CRITICAL All 20+ service credentials are publicly known CHANGE_ME_* strings — found by 4 perspectives Extend init.sh with openssl rand calls
3 Add application service containers to docker-compose.yml CRITICAL Platform is completely non-functional out of the box — docker compose up starts only databases Add all 9 service definitions
4 Add execution:read to ALL_SCOPES in token-service.ts CRITICAL All execution GET endpoints are broken for all users including admins Single-line fix
5 Fix BffClient to send X-App-Id header CRITICAL Every app-sdk hook call fails with 400 — breaks the entire hosted app platform Accept appId in constructor, include in headers
6 Generate Ed25519 service key pairs in init.sh CRITICAL All /internal/* service-to-service routes fail authentication — inter-service communication is broken Extend init.sh
7 Add OP_DATABASE_URL and OP_REDIS_URL to .env.example CRITICAL Services crash on startup with cryptic Zod validation errors 2-line documentation fix
8 Add stdout/stderr transport to logger HIGH docker logs captures nothing; Redis failures silently drop all logs — complete ops blindness Add console transport to createApp()
9 Add HTTP security headers middleware HIGH No HSTS, no X-Content-Type-Options, no X-Frame-Options on any response Middleware in createApp()
10 Fix post-bootstrap routing to render inside AppShell CRITICAL After bootstrap, dashboard renders without navigation sidebar — user is trapped on a bare page Redirect to proper authenticated route

All Findings

CRITICAL (13)

ID Category Component Pain Fix Perspectives
C-01 Security services/gateway/src/services/proxy-service.ts (HEADERS_TO_STRIP) X-User-Context header is not stripped from external requests, enabling full identity impersonation by any caller Add 'x-user-context' to HEADERS_TO_STRIP Security Reviewer
C-02 Security docker/redis/users.acl, docker/pgbouncer/userlist.txt, docker/postgres/init.sql All service passwords hardcoded as CHANGE_ME_* — publicly known, committed to source Generate unique random passwords in init.sh using openssl rand Data Engineer, Ops Admin, Security Reviewer, New User
C-03 Reliability docker/docker-compose.yml (services section) Only infrastructure containers (Postgres, Redis, PgBouncer) are defined — application services are absent; docker compose up starts an empty platform Add all 9 application service definitions Ops Admin, New User
C-04 Security services/auth/src/services/token-service.ts (ALL_SCOPES) execution:read scope is missing from ALL_SCOPES — all execution GET endpoints return 403 for all users including admins Add execution:read to ALL_SCOPES and role scope assignments Security Reviewer
C-05 Security docker/docker-compose.yml, all services No TLS anywhere in the stack — all service-to-service and client-to-service communication is plaintext Add reverse proxy (Caddy/nginx), enable PostgreSQL and Redis TLS Ops Admin, Security Reviewer
C-06 Reliability docker/init/init.sh Ed25519 service key pairs are never generated — all /internal/* service-to-service routes fail authentication at startup Extend init.sh to generate Ed25519 key pairs and inject them as environment variables Ops Admin
C-07 DX .env.example OP_DATABASE_URL and OP_REDIS_URL are absent from .env.example — services crash on first run with opaque Zod validation errors rather than actionable messages Add both variables with documented defaults Ops Admin, New User
C-08 DX packages/app-sdk/src/client/BffClient.ts X-App-Id header is never sent — every app-sdk hook call (useQuery, useMutation, useSubscription) fails with HTTP 400, breaking the entire hosted app platform Accept appId in BffClient constructor; include X-App-Id in all request headers App Developer
C-09 DX packages/app-sdk/src/provider/AppProvider.tsx, PermissionCache.ts Permission response shape from BFF is incompatible with what PermissionCache expects — all permission checks silently return false Align response envelope format between BFF and cache App Developer
C-10 DX packages/cli/src/commands/plugin/index.ts (createAction) op plugin create generates a scaffold that does not compile — missing imports and incorrect type references Delegate scaffold generation to plugin-sdk's generateScaffold() Plugin Author
C-11 DX packages/cli/src/commands/plugin/index.ts (packAction) op plugin pack is a non-functional stub that exits immediately with no output or error Wire to plugin-sdk's packPlugin() Plugin Author
C-12 DX packages/cli/src/commands/plugin/index.ts (simulateHookAction) op plugin simulate-hook requires a running server but plugin-sdk has a local, server-free implementation Delegate to SDK's runSimulateHook() Plugin Author
C-13 UX packages/frontend/src/router.tsx After completing bootstrap, the dashboard is rendered outside AppShell — no navigation sidebar, no header; user cannot navigate anywhere Redirect to the proper authenticated route that renders inside AppShell New User

HIGH (35)

ID Category Component Pain Fix Perspectives
H-01 Security packages/core/src/middleware/auth.ts Blanket /internal/* auth bypass — any external request that reaches an /internal/ path skips authentication entirely Remove blanket bypass; use explicit, per-route allowlists Security Reviewer
H-02 Security services/auth/src/services/auth-service.ts JWT tokens delivered only in response body — no httpOnly cookie option, making XSS token theft straightforward Implement dual-mode token delivery (body + secure httpOnly cookie) Security Reviewer
H-03 Security services/auth/src/services/auth-service.ts Password reset link is returned directly in the API response when SMTP is not configured — production deployments leak reset URLs to callers Guard against returning reset links in non-development environments Security Reviewer
H-04 Security services/auth/src/services/api-key-service.ts No scope validation on API key creation — callers can request scopes they do not possess, allowing privilege escalation via API keys Validate that requested scopes are a strict subset of the requesting user's scopes Security Reviewer
H-05 Security services/auth/src/routes/users.ts No role validation on user update endpoint — any authenticated user can set another user's role to any value including platform-admin Validate role names against allowed list; enforce role hierarchy on assignment Security Reviewer
H-06 Security services/auth/src/routes/users.ts Deactivating a user does not revoke their active sessions or tokens — deactivated users retain access until token expiry Revoke all tokens and sessions on user deactivation Security Reviewer
H-07 Security services/gateway/src/routes/admin.ts Role check uses string 'admin' but the actual role name is 'platform-admin' — admin routes are inaccessible to real admins Use scope-based check instead of role string comparison Security Reviewer, Ops Admin
H-08 Security services/auth/src/services/token-service.ts Replay detection uses Redis SCAN, which is a DoS vector on large keyspaces — scanning can block the Redis event loop Replace with per-family Redis set for O(1) lookup Security Reviewer
H-09 Security All services No HTTP security headers on any response — missing Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options, Content-Security-Policy Add security headers middleware to createApp() Ops Admin, Security Reviewer
H-10 Security docker/docker-compose.yml Docker socket proxy configured with POST=1 DELETE=1 — grants containers ability to create and delete arbitrary Docker resources Restrict to CONTAINERS_CREATE=1 only; audit all proxy permissions Ops Admin, Security Reviewer
H-11 Security services/execution/src/services/context-call-handler.ts SSRF via DNS rebinding — the handler resolves hostnames without validating that they do not resolve to internal RFC-1918 addresses Add DNS resolution checking before establishing outbound connections Plugin Author, Security Reviewer
H-12 Reliability packages/core/src/logger.ts All logs are published only to Redis pub/sub — docker logs captures nothing; Redis failures cause total log loss with no fallback Add stdout/stderr transport as primary; keep Redis as secondary Ops Admin
H-13 Reliability services/*/src/index.ts No uncaughtException or unhandledRejection handlers — unhandled errors silently terminate services without logging or alerting Add process error handlers that log and trigger graceful shutdown Ops Admin
H-14 Reliability docker/docker-compose.yml No resource limits (memory, cpus) on any container — a single runaway service can starve the entire host Add deploy.resources.limits to each service definition Ops Admin
H-15 Reliability All services No backup or restore procedure exists — data loss is unrecoverable Create Postgres dump scripts, Redis snapshot configuration, and documented restore runbook Ops Admin
H-16 DX docs/ No operational documentation — no deployment guide, operations runbook, upgrade procedure, or scaling guide Create docs/operations/ with deployment, ops, upgrade, and scaling guides Ops Admin, New User
H-17 Reliability services/ingestion/src/services/sync-service.ts Records are inserted inline during sync AND in a subsequent batch job — every record is double-written to the database Remove inline insert; allow the batch job to be the sole writer Data Engineer
H-18 Reliability services/ingestion/src/services/retention-service.ts cleanupDeletedConnectors is a no-op — deleted connectors accumulate orphaned rows indefinitely Implement findDeletedBefore query and table cleanup logic Data Engineer
H-19 DX packages/cli/src/commands/connector/index.ts triggerAction polls the wrong endpoint for sync progress — users receive no meaningful status feedback Fix to poll the correct progress endpoint Data Engineer
H-20 DX packages/sdk/src/resources/apps.ts SDK App methods are bare CRUD only — no build, deploy, rollback, or file management methods Add build, deploy, rollback, and file operation methods App Developer
H-21 DX packages/app-sdk/src/hooks/useQuery.ts, BffClient.ts Response is double-wrapped in the envelope — consuming code must unwrap twice or receive undefined data Fix envelope unwrapping to a single layer App Developer
H-22 DX services/app/src/routes/bff.ts PATCH, PUT, and DELETE data routes are absent from the BFF — apps can read but cannot mutate data Add missing BFF mutation routes App Developer
H-23 DX services/app/src/routes/apps.ts Type declarations endpoint returns hand-authored, inaccurate TypeScript types — types drift from actual implementation Auto-generate from app-sdk source using tsc --declaration or ts-morph App Developer
H-24 Security packages/sdk/src/auth/pkce.ts PKCE constructor auto-redirects the browser on instantiation — importing the class triggers a navigation side effect Add an explicit login() method; constructor must be side-effect-free App Developer
H-25 DX packages/plugin-sdk/src/types/hooks.ts HookPayload.data is typed as Record<string, unknown> for all hook stages — no per-stage type narrowing Create a discriminated union keyed on stage Plugin Author
H-26 Security services/execution/src/services/context-call-handler.ts context.getCredential() is restricted to connector-run execution type — auth providers and destinations cannot access their own credentials Extend credential access to auth-provider and destination execution types Plugin Author
H-27 Security services/plugin/src/services/plugin-service.ts GPG signature verification is declared in the schema (gpgFingerprint) but never performed — plugins are accepted without verification Integrate openpgp to verify signatures; or remove gpgFingerprint field and document the decision Plugin Author
H-28 Reliability services/plugin/src/services/plugin-service.ts activatePlugin is a no-op stub that returns success without performing any status transition Implement actual status transition logic Plugin Author
H-29 DX packages/plugin-sdk No dev server or full lifecycle testing tooling — plugin authors must deploy to a live server to test Create op plugin dev command with hot-reload and local hook invocation Plugin Author
H-30 DX packages/plugin-sdk/src/testing/mock-context.ts Single generic mock for all plugin types — connector-run, auth-provider, and destination receive identical mock shapes Add per-type mock factories with realistic, type-correct data Plugin Author
H-31 DX packages/cli/src/commands/plugin/index.ts CLI sends file field but plugin service expects bundle — plugin uploads silently fail field validation Change CLI to send bundle Plugin Author
H-32 Reliability services/app/src/services/build-service.ts Build dispatch is fire-and-forget with no recovery — builds stuck in building state after a crash are never retried or timed out Add startup scan for orphaned builds, configurable timeout, and retry logic App Developer
H-33 UX packages/frontend/src/components/wizard/steps/MasterKeyStep.tsx 60-second countdown to confirm master key is too aggressive for a high-stakes, one-time operation Increase to 5 minutes; add a download-as-file button New User
H-34 UX packages/frontend/src/pages/connectors/NewConnectorPage.tsx Connector creation page shows an empty plugin list with no guidance — new users reach a dead end immediately Add a link to the plugin marketplace; ship at least one built-in connector New User
H-35 UX packages/frontend/src/components/layout/Topbar.tsx User and tenant are displayed as raw UUIDs Replace with email/name fetched from auth/me endpoint New User
H-36 UX packages/frontend/src/pages/ontology/OntologyPage.tsx "Ontology" terminology is opaque to non-specialists — new users do not know what the page is for Add contextual help text; consider relabeling as "Data Models" New User
H-37 Reliability packages/frontend/src/pages/BootstrapGatePage.tsx No error boundary on the first page a new user sees — any error renders a blank white screen with no recovery option Add errorComponent with a retry button New User
H-38 UX packages/frontend/src/pages/pipelines/PipelineBuilderPage.tsx Pipeline step editor is non-functional — clicking steps opens no configuration panel Add real step configuration UI New User
H-39 DX README.md No documentation of infrastructure prerequisites — users encounter failures before running a single command Document required tools, versions, and infra setup before pnpm dev instructions New User
H-40 UX services/ingestion/src/services/sync-service.ts Sync run history is sourced from BullMQ job records only — history is transient and lost on queue flush Store sync runs in a Postgres table for durable, queryable history Data Engineer
H-41 UX services/ingestion/src/schemas/index.ts Cron expressions are accepted without validation — invalid expressions cause silent scheduling failures Add cron-parser validation at the API boundary Data Engineer
H-42 UX packages/cli/src/commands/connector/index.ts createAction is missing --credentials, --sync-mode, and --is-enabled options Add credential file path and mode options Data Engineer
H-43 Performance services/ingestion/src/services/connector-service.ts listConnectors executes N+1 queries — one query per connector to fetch sync state JOIN sync_state table; push all filters to the database Data Engineer
H-44 Reliability services/ontology/src/index.ts SIGTERM handler completes cleanup but never calls process.exit(0) — container shutdown hangs until Docker's kill timeout Add process.exit(0) call and a hard shutdown timeout Ops Admin
H-45 Reliability services/*/src/index.ts All services hardcode version '0.0.0' in health and metrics responses Read version from package.json or a BUILD_VERSION environment variable Ops Admin
H-46 Performance docker/redis/redis.conf No maxmemory limit configured — Redis will consume all available host memory under load Set a 256mb default with allkeys-lru eviction policy Ops Admin
H-47 Performance All services OpenTelemetry is entirely stubbed out — no traces, no metrics, no collector configured Add OTEL Collector sidecar, Jaeger for traces, Prometheus for metrics Ops Admin
H-48 DX packages/cli/src/ No mapping command group — data engineers cannot manage ontology mappings from the CLI Add op mapping list/create/update/delete commands Data Engineer

Note: IDs H-36 through H-48 correspond to findings 50-62 in the raw dataset. The table above lists all 35 HIGH findings.


MEDIUM (31)

ID Category Component Pain Fix Perspectives
M-01 Security packages/core/src/middleware/service-auth.ts X-User-Context header is forwarded between services but never HMAC-signed or validated — any service can forge it Add HMAC signing on emission and signature validation on receipt Security Reviewer
M-02 Security services/auth/src/services/auth-service.ts User enumeration via distinct error messages for "user not found" vs "wrong password" Return the same generic error for all authentication failures Security Reviewer
M-03 Security services/gateway/src/index.ts Rate limiter uses client-controllable X-Forwarded-For header as the rate limit key Use actual TCP source IP (req.socket.remoteAddress) Security Reviewer
M-04 Security services/auth/src/services/token-service.ts HS256 symmetric JWT signing — compromise of the signing secret breaks all token verification across all services Migrate to RS256 or EdDSA asymmetric signing Security Reviewer
M-05 Security docker/redis/redis.conf protected-mode no is set — Redis accepts unauthenticated connections from any network interface Set protected-mode yes Security Reviewer
M-06 Security Gateway and all services No request body size limit — large payloads can exhaust memory Add configurable size limit; return 413 on exceed Ops Admin
M-07 Security docker/docker-compose.yml No container security hardening — containers run with excess capabilities and writable root filesystems Add no-new-privileges: true, cap_drop: [ALL], read_only: true Ops Admin, Security Reviewer
M-08 Security services/ontology/src/services/mapping-service.ts Expression transforms are built via string concatenation — potential for expression injection Replace with JSONata or sandboxed expression evaluation Data Engineer
M-09 Security services/ingestion/src/services/credential-service.ts No key rotation mechanism for encrypted connector credentials Implement a key rotation job with re-encryption Data Engineer
M-10 Reliability services/ingestion/src/services/sync-service.ts Stale running state with no watchdog — crashed syncs are never reset, blocking future runs for that connector Add a periodic stale-sync detection and reset job Data Engineer
M-11 DX packages/cli/src/commands/schedule/index.ts CLI sends cron field but service expects cronExpr — schedule creation silently fails field mapping Change CLI to send cronExpr Data Engineer
M-12 DX packages/cli/src/commands/exec/index.ts Help text advertises Python support that does not exist Update description to js\|ts only Data Engineer
M-13 DX packages/sdk/src/resources/data.ts Proxy-based entity access returns any — no TypeScript autocompletion or type safety for data queries Add createTypedClient<T>() factory that returns typed query methods App Developer
M-14 DX packages/app-sdk/src/hooks/useSubscription.ts No automatic cache invalidation on entity mutation events — UIs go stale after writes Auto-invalidate related queries on received entity events App Developer
M-15 Reliability services/app/src/services/widget-service.ts Widget registry is in-memory only — all registered widgets are lost on service restart Persist widget registry to Postgres App Developer
M-16 DX packages/plugin-sdk/src/dev/pack.ts tar flattens directory structure — plugins with sub-directories lose their file layout on pack Preserve relative paths in the archive Plugin Author
M-17 UX packages/frontend/src/pages/auth/LoginPage.tsx "Register" link is visible but navigates to a non-functional or absent page Implement a registration form or remove the link until registration is built New User
M-18 UX packages/frontend/src/pages/settings/SettingsPage.tsx Settings sidebar navigation uses separate top-level routes — navigating settings causes full-page reloads and loses sub-route state Make settings sub-pages children of the settings layout route New User
M-19 Reliability docker/docker-compose.yml No stop_grace_period or Docker log rotation configured — containers are force-killed before graceful shutdown completes; logs grow unbounded Set stop_grace_period: 45s; add logging config with size rotation Ops Admin
M-20 DX Auth service / CLI No tenant management API beyond initial bootstrap — operators cannot create, rename, or delete tenants after setup Add CRUD routes to auth service and corresponding CLI commands Ops Admin
M-21 UX packages/frontend/src/pages/dashboard/DashboardPage.tsx Quick Start panel checks static booleans rather than actual platform state — users who have completed steps still see them as incomplete Base checklist on real data (connector count, entity count); add a guided first-run flow New User
M-22 Documentation packages/plugin-sdk, packages/sdk No README, no API reference, no usage examples in either SDK package Create getting-started guides; add JSDoc examples to all public methods Plugin Author, App Developer
M-23 Reliability services/plugin/src/services/instance-service.ts Plugin instance configuration validated only with minimal JSON Schema — required fields and type constraints are missing Integrate Ajv with strict mode for proper schema validation Plugin Author

Note: The raw dataset contained 31 MEDIUM findings. IDs M-01 through M-23 above represent all entries; the table collapses M-22/M-23 which map to raw findings 84-85.


LOW (6)

ID Category Component Pain Fix Perspectives
L-01 DX packages/cli/src/index.ts 20 flat, uncategorized command groups — op --help output is overwhelming for new users Add command categories (Data, Apps, Plugins, Admin) Data Engineer
L-02 DX packages/sdk/src/client.ts SDK client throws on a trailing slash in baseUrl — a common user mistake becomes an uncaught error Silently strip trailing slashes from baseUrl App Developer
L-03 DX packages/sdk/src/resources/data.ts Validation failures throw plain Error instead of OnePlatformError — callers cannot distinguish SDK errors from other errors Use ValidationError (subclass of OnePlatformError) App Developer
L-04 UX packages/frontend/src/pages/settings/ProfilePage.tsx Profile page shows empty default fields — user's actual profile data is never fetched Add useQuery call to pre-populate form fields from auth/me New User
L-05 DX docker/docker-compose.yml Volume declarations for application services exist but those services are not yet defined — unused volumes cause confusion Remove unused volume declarations until the corresponding services are added Ops Admin
L-06 Security docker/Dockerfile.sandbox Missing V8 hardening flags in sandbox container Add --disallow-code-generation-from-strings and --jitless to Node invocation Security Reviewer

Finding Distribution by Perspective

This table shows how many findings each perspective contributed (pre-deduplication). Findings claimed by multiple perspectives are counted once per perspective.

Perspective CRITICAL HIGH MEDIUM LOW Total (raw)
security-reviewer 5 12 7 1 25
ops-admin 4 9 5 1 19
app-developer 3 7 4 2 16
new-user 3 7 4 1 15
plugin-author 3 7 3 0 13
data-engineer 2 8 6 1 17
Multi-perspective 4 5 2 0 11

Findings flagged by 2 or more perspectives independently are the highest-confidence items — they represent failures visible from multiple angles of the system.


Cross-Reference: Findings by Component Area

Area CRITICAL HIGH MEDIUM LOW
Auth service 1 6 2 0
Gateway 1 2 1 0
Docker / Infra 3 5 3 1
CLI 3 4 2 1
Ingestion service 0 5 3 0
App SDK / BFF 2 4 2 1
Plugin SDK / service 3 5 2 0
Frontend 1 4 2 1
Core / logger 0 2 1 0
SDK (platform) 0 1 2 2
Execution service 0 2 0 0
Ontology service 0 1 1 0
Documentation 0 1 1 0

Comparison with v1 Analysis

Metric v1 v2
Findings 108 85 unique (202 raw)
Perspectives 4 6
CRITICAL identified Not categorized 13
New perspectives added plugin-author, security-reviewer
Security findings Scattered 24 total (5 CRITICAL, 11 HIGH, 7 MEDIUM, 1 LOW)

The addition of the security-reviewer and plugin-author perspectives in v2 surfaced the header injection vulnerability (C-01), the scope coverage gap (C-04), the GPG verification stub (H-27), and the Docker socket over-permission (H-10) — none of which appeared in v1.