Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

187 lines
24 KiB
JSON

[
{ "id": "T001", "description": "Migration creates `inbound_webhooks` with tenant in composite PK", "implemented": true, "featureIds": ["F001"] },
{ "id": "T002", "description": "Migration creates `inbound_webhook_deliveries` with tenant in composite PK", "implemented": true, "featureIds": ["F002"] },
{ "id": "T003", "description": "Slug uniqueness enforced per-tenant, not globally", "implemented": true, "featureIds": ["F001", "F014"] },
{ "id": "T004", "description": "`lookupAlgaEntityByExternalId` resolves via `tenant_external_entity_mappings` and respects `integration_type=webhookSlug` scoping", "implemented": true, "featureIds": ["F004"] },
{ "id": "T004a", "description": "`writeEntityMapping` inserts a row with correct unique constraint behavior; duplicate write is idempotent", "implemented": true, "featureIds": ["F005"] },
{ "id": "T004b", "description": "Reserved integration_type collision: user webhook slug `ninjaone` rejected (or auto-namespaced) so it cannot pollute bundled integration mappings", "implemented": true, "featureIds": ["F003"] },
{ "id": "T005", "description": "Migration is idempotent (re-running is safe)", "implemented": true, "featureIds": ["F001", "F002"] },
{ "id": "T006", "description": "`inbound_webhook` permission seeded for admin role", "implemented": true, "featureIds": ["F006"] },
{ "id": "T007", "description": "Non-admin role does NOT receive inbound_webhook permissions by default", "implemented": true, "featureIds": ["F006"] },
{ "id": "T010", "description": "Zod validation rejects upsert with bogus auth_type", "implemented": true, "featureIds": ["F011"] },
{ "id": "T011", "description": "Zod validation rejects HMAC config without signature header name", "implemented": true, "featureIds": ["F011"] },
{ "id": "T012", "description": "Zod validation rejects direct_action handler without action name", "implemented": true, "featureIds": ["F011"] },
{ "id": "T013", "description": "Zod validation rejects workflow handler without workflow_id", "implemented": true, "featureIds": ["F011"] },
{ "id": "T014", "description": "Zod validation rejects URL-unsafe slug characters", "implemented": true, "featureIds": ["F011", "F014"] },
{ "id": "T020", "description": "`listInboundWebhooks` returns only current tenant's webhooks", "implemented": true, "featureIds": ["F012"] },
{ "id": "T021", "description": "`upsertInboundWebhook` rejects duplicate slug in same tenant", "implemented": true, "featureIds": ["F014"] },
{ "id": "T022", "description": "`upsertInboundWebhook` allows same slug across different tenants", "implemented": true, "featureIds": ["F014"] },
{ "id": "T023", "description": "`upsertInboundWebhook` writes secret to vault, not DB column", "implemented": true, "featureIds": ["F014", "F016"] },
{ "id": "T024", "description": "`getInboundWebhook` does NOT return secret in response", "implemented": true, "featureIds": ["F013"] },
{ "id": "T025", "description": "`rotateInboundWebhookSecret` invalidates old secret immediately", "implemented": true, "featureIds": ["F016"] },
{ "id": "T026", "description": "`deleteInboundWebhook` cascades to deliveries OR retains deliveries (decide and test)", "implemented": true, "featureIds": ["F015"] },
{ "id": "T027", "description": "Server actions reject when user lacks `inbound_webhook` permission", "implemented": true, "featureIds": ["F102"] },
{ "id": "T028", "description": "Server actions require tenant context (withAuth)", "implemented": true, "featureIds": ["F012", "F013", "F014", "F015"] },
{ "id": "T030", "description": "POST to `/api/inbound/<tenant>/<slug>` with valid HMAC returns 200 + delivery_id", "implemented": true, "featureIds": ["F030", "F033"] },
{ "id": "T031", "description": "POST with invalid HMAC returns 401, no delivery row beyond rejected-auth log", "implemented": true, "featureIds": ["F033", "F037"] },
{ "id": "T032", "description": "POST with mismatched signature header name returns 401", "implemented": true, "featureIds": ["F033"] },
{ "id": "T033", "description": "POST with valid Bearer token succeeds", "implemented": true, "featureIds": ["F034"] },
{ "id": "T034", "description": "POST with bad Bearer token returns 401", "implemented": true, "featureIds": ["F034"] },
{ "id": "T035", "description": "POST from IP in allowlist succeeds", "implemented": true, "featureIds": ["F035"] },
{ "id": "T036", "description": "POST from IP outside allowlist returns 401", "implemented": true, "featureIds": ["F035"] },
{ "id": "T037", "description": "POST with valid path-token succeeds", "implemented": true, "featureIds": ["F036"] },
{ "id": "T038", "description": "POST with invalid path-token returns 401", "implemented": true, "featureIds": ["F036"] },
{ "id": "T039", "description": "Unknown tenant slug returns 401 (identical to bad auth — no enumeration)", "implemented": true, "featureIds": ["F037"] },
{ "id": "T040", "description": "Unknown webhook slug under valid tenant returns 401 (identical body)", "implemented": true, "featureIds": ["F037"] },
{ "id": "T041", "description": "Disabled (is_active=false) webhook returns 401", "implemented": true, "featureIds": ["F030", "F037"] },
{ "id": "T042", "description": "HMAC comparison is timing-safe (no early-return on byte mismatch)", "implemented": true, "featureIds": ["F033"] },
{ "id": "T043", "description": "Bearer comparison is timing-safe", "implemented": true, "featureIds": ["F034"] },
{ "id": "T044", "description": "Headers `Cookie` and `Authorization` are stripped before persistence", "implemented": true, "featureIds": ["F043"] },
{ "id": "T050", "description": "Header-source idempotency key extracted from configured header", "implemented": true, "featureIds": ["F038"] },
{ "id": "T051", "description": "JSONata-source idempotency key extracted from configured path", "implemented": true, "featureIds": ["F039"] },
{ "id": "T052", "description": "Duplicate idempotency key within window returns 200 no-op", "implemented": true, "featureIds": ["F040"] },
{ "id": "T053", "description": "Same idempotency key after window expires triggers fresh dispatch", "implemented": true, "featureIds": ["F040"] },
{ "id": "T054", "description": "Missing idempotency key (when source is configured) — define behavior and test (accept vs reject)", "implemented": true, "featureIds": ["F038", "F039"] },
{ "id": "T055", "description": "Different webhooks with same idempotency key dedup independently", "implemented": true, "featureIds": ["F040"] },
{ "id": "T060", "description": "Delivery row persisted with auth_status=verified before dispatch", "implemented": true, "featureIds": ["F041"] },
{ "id": "T061", "description": "Auth-rejected requests log to separate row with limited detail (no body)", "implemented": true, "featureIds": ["F041", "F043"] },
{ "id": "T062", "description": "Dispatch failure leaves delivery row with dispatch_status=failed and error message", "implemented": true, "featureIds": ["F041"] },
{ "id": "T070", "description": "Rate limit: requests above per-webhook threshold get 429", "implemented": true, "featureIds": ["F042"] },
{ "id": "T071", "description": "Rate limit isolates per webhook (one webhook hitting limit doesn't affect another)", "implemented": true, "featureIds": ["F042"] },
{ "id": "T072", "description": "Rate limit isolates per tenant", "implemented": true, "featureIds": ["F042"] },
{ "id": "T080", "description": "Sample payload capture stores first verified body within capture window", "implemented": true, "featureIds": ["F044", "F021"] },
{ "id": "T081", "description": "Capture window expires after 5 min; later requests don't overwrite", "implemented": true, "featureIds": ["F021", "F044"] },
{ "id": "T082", "description": "`clearSamplePayload` removes the saved sample", "implemented": true, "featureIds": ["F022"] },
{ "id": "T090", "description": "Action registry: `registerAction` adds a definition; `listActions` returns all registered, grouped by entityType", "implemented": true, "featureIds": ["F050"] },
{ "id": "T091", "description": "Action registry: duplicate action name throws on register (or last-wins; pick and test)", "implemented": true, "featureIds": ["F050"] },
{ "id": "T092", "description": "Bootstrap loads all v1 package action contributions before first inbound request", "implemented": true, "featureIds": ["F053"] },
{ "id": "T093", "description": "Field mapping evaluator: JSONata expression evaluated correctly against request body", "implemented": true, "featureIds": ["F054"] },
{ "id": "T094", "description": "Field mapping: malformed JSONata → failed delivery, not 500", "implemented": true, "featureIds": ["F054", "F055"] },
{ "id": "T095", "description": "Field mapping: missing required target field → failed delivery with clear error", "implemented": true, "featureIds": ["F055"] },
{ "id": "T096", "description": "Lookup-miss in any `*ByExternalId` action → failed delivery with `lookup_miss` reason", "implemented": true, "featureIds": ["F056"] },
{ "id": "T1010", "description": "`createTicket` action creates ticket with mapped fields; tenant scoped", "implemented": true, "featureIds": ["F1010", "F054"] },
{ "id": "T1011", "description": "`createTicket` writes mapping row when an `external_id` is mapped", "implemented": true, "featureIds": ["F1010", "F005"] },
{ "id": "T1012", "description": "`createTicket` records ticket_id on delivery row", "implemented": true, "featureIds": ["F1010"] },
{ "id": "T1013", "description": "`updateTicketByExternalId` resolves ticket via mappings table and updates status/priority/assignee", "implemented": true, "featureIds": ["F1011", "F004"] },
{ "id": "T1014", "description": "`updateTicketByExternalId` no mapping found → failed delivery", "implemented": true, "featureIds": ["F1011", "F056"] },
{ "id": "T1015", "description": "`addTicketCommentByExternalId` appends comment to resolved ticket", "implemented": true, "featureIds": ["F1012"] },
{ "id": "T1016", "description": "`changeTicketStatusByExternalId` transitions ticket through valid status only (invalid status → failed delivery)", "implemented": true, "featureIds": ["F1013"] },
{ "id": "T1020", "description": "`upsertClientByExternalId` creates client when mapping absent and writes mapping row", "implemented": true, "featureIds": ["F1020", "F005"] },
{ "id": "T1021", "description": "`upsertClientByExternalId` updates client when mapping resolves", "implemented": true, "featureIds": ["F1020", "F004"] },
{ "id": "T1022", "description": "`setClientActiveByExternalId` toggles active state correctly", "implemented": true, "featureIds": ["F1021"] },
{ "id": "T1030", "description": "`upsertContactByExternalId` creates or updates a client_user record", "implemented": true, "featureIds": ["F1030"] },
{ "id": "T1031", "description": "`upsertContactByExternalId` requires a client linkage (either mapped client_external_id or direct client_id)", "implemented": true, "featureIds": ["F1030"] },
{ "id": "T1040", "description": "`upsertAssetByExternalId` for RMM-shaped payload delegates to `ingestNormalizedRmmDeviceSnapshot`", "implemented": true, "featureIds": ["F1040"] },
{ "id": "T1041", "description": "RMM-path asset upsert produces identical record shape to NinjaOne/Tactical RMM ingestion (regression vs sample)", "implemented": true, "featureIds": ["F1040"] },
{ "id": "T1042", "description": "`upsertAssetByExternalId` for non-RMM payload takes plain asset upsert path", "implemented": true, "featureIds": ["F1041"] },
{ "id": "T1050", "description": "`markInvoicePaidByExternalId` marks matching invoice paid", "implemented": true, "featureIds": ["F1050"] },
{ "id": "T1051", "description": "`markInvoicePaidByExternalId` lookup-miss → failed delivery", "implemented": true, "featureIds": ["F1050", "F056"] },
{ "id": "T1052", "description": "`markInvoicePaidByExternalId` is idempotent: re-applying to already-paid invoice does not double-mark or error", "implemented": true, "featureIds": ["F1052"] },
{ "id": "T1053", "description": "`updateInvoiceStatusByExternalId` updates invoice status via mapped value", "implemented": true, "featureIds": ["F1051"] },
{ "id": "T1060", "description": "`createTimeEntry` creates a time entry with mapped user, work item, duration, billable flag", "implemented": true, "featureIds": ["F1060"] },
{ "id": "T1070", "description": "`createProjectTask` creates a task under a project resolved by external_id or direct project_id", "implemented": true, "featureIds": ["F1070"] },
{ "id": "T1071", "description": "`updateProjectTaskStatusByExternalId` updates status via mappings lookup", "implemented": true, "featureIds": ["F1071"] },
{ "id": "T1080", "description": "`addTagToEntityByExternalId` attaches tag to ticket when entity_type=ticket", "implemented": true, "featureIds": ["F1080"] },
{ "id": "T1081", "description": "`addTagToEntityByExternalId` attaches tag to client when entity_type=client", "implemented": true, "featureIds": ["F1080"] },
{ "id": "T1082", "description": "`addTagToEntityByExternalId` rejects unsupported entity_type with clear error", "implemented": true, "featureIds": ["F1080"] },
{ "id": "T110", "description": "Workflow handler starts a workflow run with the documented envelope shape", "implemented": true, "featureIds": ["F060", "F061"] },
{ "id": "T111", "description": "Envelope includes `source`, `body`, `headers`, `verified`, `delivery_id`, `idempotency_key`, `received_at`", "implemented": true, "featureIds": ["F061"] },
{ "id": "T112", "description": "Envelope `headers` is filtered (no Cookie/Authorization)", "implemented": true, "featureIds": ["F061", "F043"] },
{ "id": "T113", "description": "Delivery row stores workflow_run_id after successful trigger", "implemented": true, "featureIds": ["F062"] },
{ "id": "T114", "description": "Workflow engine error on trigger → failed delivery with error message", "implemented": true, "featureIds": ["F063"] },
{ "id": "T115", "description": "Workflow run failure AFTER trigger does NOT mark delivery failed", "implemented": true, "featureIds": ["F063"] },
{ "id": "T120", "description": "Webhook payload context adapter builds path tree from sample payload", "implemented": true, "featureIds": ["F070", "F071"] },
{ "id": "T121", "description": "Adapter handles nested objects, arrays, mixed types", "implemented": true, "featureIds": ["F071"] },
{ "id": "T122", "description": "Adapter handles empty/null sample (returns minimal tree, no crash)", "implemented": true, "featureIds": ["F071"] },
{ "id": "T123", "description": "ExpressionTextArea autocompletes paths from adapter", "implemented": true, "featureIds": ["F072", "F088"] },
{ "id": "T130", "description": "Settings page renders tabbed UI with Inbound and Outbound tabs", "implemented": true, "featureIds": ["F080"] },
{ "id": "T131", "description": "Outbound tab functions identically to pre-refactor (no regressions)", "implemented": true, "featureIds": ["F080"] },
{ "id": "T132", "description": "Inbound list view shows table with name/URL/handler/last delivery/active", "implemented": true, "featureIds": ["F081"] },
{ "id": "T133", "description": "Create dialog: Identity section accepts name, slug, description", "implemented": true, "featureIds": ["F082"] },
{ "id": "T134", "description": "Auth section conditionally renders HMAC fields", "implemented": true, "featureIds": ["F083"] },
{ "id": "T135", "description": "Auth section conditionally renders Bearer fields", "implemented": true, "featureIds": ["F083"] },
{ "id": "T136", "description": "Auth section conditionally renders IP allowlist fields", "implemented": true, "featureIds": ["F083"] },
{ "id": "T137", "description": "Secret displayed once on creation, never again", "implemented": true, "featureIds": ["F084"] },
{ "id": "T138", "description": "Rotate secret flow displays new secret once", "implemented": true, "featureIds": ["F016", "F084"] },
{ "id": "T139", "description": "Idempotency section renders source dropdown + value input", "implemented": true, "featureIds": ["F085"] },
{ "id": "T140", "description": "Handler section switches between direct_action and workflow views", "implemented": true, "featureIds": ["F086"] },
{ "id": "T141", "description": "Action dropdown lists all registered actions", "implemented": true, "featureIds": ["F087"] },
{ "id": "T142", "description": "Selecting action renders its target fields with ExpressionTextArea rows", "implemented": true, "featureIds": ["F088"] },
{ "id": "T143", "description": "Workflow dropdown lists tenant's workflows", "implemented": true, "featureIds": ["F091"] },
{ "id": "T144", "description": "Workflow envelope info card displays correct shape", "implemented": true, "featureIds": ["F091"] },
{ "id": "T145", "description": "Sample capture button toggles capture mode and shows countdown", "implemented": true, "featureIds": ["F089"] },
{ "id": "T146", "description": "Sample tree side panel renders captured payload paths", "implemented": true, "featureIds": ["F090"] },
{ "id": "T147", "description": "Clicking a path in tree inserts it into focused ExpressionTextArea", "implemented": true, "featureIds": ["F090"] },
{ "id": "T148", "description": "Active toggle persists state", "implemented": true, "featureIds": ["F092"] },
{ "id": "T149", "description": "Auto-disable banner shows when auto_disabled_at is set", "implemented": true, "featureIds": ["F092"] },
{ "id": "T160", "description": "Delivery log list paginates and filters by webhook + status", "implemented": true, "featureIds": ["F093"] },
{ "id": "T161", "description": "Delivery detail drawer shows request body, headers, response, latency", "implemented": true, "featureIds": ["F094"] },
{ "id": "T162", "description": "Replay button creates new delivery row with is_replay=true", "implemented": true, "featureIds": ["F020", "F095"] },
{ "id": "T163", "description": "Replay uses current config (mapping changes reflected)", "implemented": true, "featureIds": ["F020"] },
{ "id": "T164", "description": "Replayed delivery links back to original via replayed_from", "implemented": true, "featureIds": ["F020"] },
{ "id": "T165", "description": "Synthetic test dialog accepts custom body + headers and dispatches in-process", "implemented": true, "featureIds": ["F023", "F096"] },
{ "id": "T170", "description": "No hardcoded English strings in new UI components (i18n scan passes)", "implemented": true, "featureIds": ["F097"] },
{ "id": "T171", "description": "All interactive elements have kebab-case `id` attributes (UI reflection scan passes)", "implemented": true, "featureIds": ["F098"] },
{ "id": "T180", "description": "Feature flag off: Settings tab hidden", "implemented": true, "featureIds": ["F100"] },
{ "id": "T181", "description": "Feature flag off: `/api/inbound/*` returns 404", "implemented": true, "featureIds": ["F101"] },
{ "id": "T182", "description": "Feature flag on for specific tenant only: other tenants unaffected", "implemented": true, "featureIds": ["F100", "F101"] },
{ "id": "T190", "description": "All inbound webhook queries include `tenant` in WHERE", "implemented": true, "featureIds": ["F001", "F012", "F013", "F032"] },
{ "id": "T191", "description": "All inbound delivery queries include `tenant` in WHERE", "implemented": true, "featureIds": ["F002", "F018", "F019"] },
{ "id": "T192", "description": "Cross-tenant delivery lookup blocked (tenant A cannot view tenant B's deliveries)", "implemented": true, "featureIds": ["F019", "F102"] },
{ "id": "T193", "description": "Cross-tenant webhook config access blocked", "implemented": true, "featureIds": ["F013", "F102"] },
{ "id": "T200", "description": "E2E: MSP admin creates HMAC webhook, sends signed payload, ticket appears in UI", "implemented": true, "featureIds": ["F030", "F033", "F1010", "F082", "F084"] },
{ "id": "T201", "description": "E2E: Admin sets up workflow handler, payload triggers workflow run visible in runs list", "implemented": true, "featureIds": ["F060", "F091"] },
{ "id": "T202", "description": "E2E: Failed delivery shows in log, replay succeeds after fixing config", "implemented": true, "featureIds": ["F020", "F093", "F095"] },
{ "id": "T300", "description": "`GET /api/v1/inbound-webhooks` returns 200 + list scoped to tenant", "implemented": true, "featureIds": ["F200"] },
{ "id": "T301", "description": "`POST /api/v1/inbound-webhooks` creates config and returns 201 + secret (once)", "implemented": true, "featureIds": ["F201"] },
{ "id": "T302", "description": "`GET /api/v1/inbound-webhooks/{id}` returns config without secret", "implemented": true, "featureIds": ["F202"] },
{ "id": "T303", "description": "`PUT /api/v1/inbound-webhooks/{id}` updates fields and persists", "implemented": true, "featureIds": ["F202"] },
{ "id": "T304", "description": "`DELETE /api/v1/inbound-webhooks/{id}` returns 204", "implemented": true, "featureIds": ["F202"] },
{ "id": "T305", "description": "`POST /api/v1/inbound-webhooks/{id}/rotate-secret` returns new secret once", "implemented": true, "featureIds": ["F203"] },
{ "id": "T306", "description": "`POST /api/v1/inbound-webhooks/{id}/test` dispatches synthetic request in-process", "implemented": true, "featureIds": ["F204"] },
{ "id": "T307", "description": "`POST /api/v1/inbound-webhooks/{id}/capture-sample` enables capture window", "implemented": true, "featureIds": ["F205"] },
{ "id": "T308", "description": "`DELETE /api/v1/inbound-webhooks/{id}/capture-sample` clears captured sample", "implemented": true, "featureIds": ["F205"] },
{ "id": "T309", "description": "`GET /api/v1/inbound-webhooks/{id}/deliveries` paginates and filters", "implemented": true, "featureIds": ["F206"] },
{ "id": "T310", "description": "`GET /api/v1/inbound-webhooks/{id}/deliveries/{deliveryId}` returns full delivery", "implemented": true, "featureIds": ["F207"] },
{ "id": "T311", "description": "`POST .../deliveries/{deliveryId}/replay` creates new delivery row linked to original", "implemented": true, "featureIds": ["F208"] },
{ "id": "T312", "description": "`GET /api/v1/inbound-webhooks/actions` returns all registered actions with target field schemas", "implemented": true, "featureIds": ["F209"] },
{ "id": "T313", "description": "Action discovery endpoint output matches registry contents (no drift)", "implemented": true, "featureIds": ["F209", "F050"] },
{ "id": "T320", "description": "Generated `alga-openapi.ce.yaml` contains every `/api/v1/inbound-webhooks/*` path", "implemented": true, "featureIds": ["F210", "F220"] },
{ "id": "T321", "description": "Generated `alga-openapi.ee.yaml` matches CE plus any EE-only entries", "implemented": true, "featureIds": ["F220"] },
{ "id": "T322", "description": "Templated receiver endpoint `/api/inbound/{tenantSlug}/{webhookSlug}` present in OpenAPI with documented headers + response codes", "implemented": true, "featureIds": ["F211"] },
{ "id": "T323", "description": "`InboundWebhookConfig` schema referenced from list/get/create responses", "implemented": true, "featureIds": ["F212"] },
{ "id": "T324", "description": "`InboundWebhookAuthConfig` discriminated union resolves correctly for each `auth_type`", "implemented": true, "featureIds": ["F214"] },
{ "id": "T325", "description": "`InboundWebhookHandlerConfig` discriminated union resolves for `direct_action` and `workflow`", "implemented": true, "featureIds": ["F215"] },
{ "id": "T326", "description": "`WorkflowWebhookEnvelope` schema present and matches runtime envelope shape", "implemented": true, "featureIds": ["F218", "F061"] },
{ "id": "T327", "description": "Contract test: each management route handler accepts/returns shapes matching its OpenAPI definition", "implemented": true, "featureIds": ["F221"] },
{ "id": "T328", "description": "Contract test: action discovery endpoint output validates against `InboundActionDefinition[]` schema", "implemented": true, "featureIds": ["F222", "F217"] },
{ "id": "T329", "description": "REST API routes reject unauthorized callers (parity with server actions)", "implemented": true, "featureIds": ["F223", "F102"] },
{ "id": "T330", "description": "REST API routes scope every query by tenant (parity with server actions)", "implemented": true, "featureIds": ["F223", "F032"] }
]