Operations API Tests — Goal
Purpose
Section titled “Purpose”Build a strongly-typed, self-contained API-test suite for the operations
component that exercises its HTTP API from the outside, and do so as a reusable
pattern — a structure any Arda backend component (accounts, a future
system-api-tests) can replicate with minimal change. operations is the
reference instance; this document scopes the pattern and its first application.
The suite reaches parity with the existing Bruno api-test coverage for
operations (item, kanban, business-affiliate, configuration/probe) and is
structured to extend beyond it. The specific assertions are secondary to the
structure: the value of this project is a template that is correct-by-layering,
contract-accurate, and cheap to run in every phase of the development cycle.
Requirements
Section titled “Requirements”Drawn from the founding discussion (technology, needs, options):
- Strongly-typed TypeScript. The wire is type-checked against the component’s
own OpenAPI, so a contract change is a compile error, not a runtime surprise.
TypeScript is chosen for closeness to the frontend stack (
arda-frontend-app): the suite can double as client API-usage examples, and infrastructure and utilities can be shared with frontend development. A full programming language (vs a test-oriented framework) also gives full control of control flow and concurrency, first-class composition of reusable elements, and a low learning curve for engineers already working in TypeScript. - Runs locally and in CI. The same suite runs from a developer shell against a local cluster and, later, from GitHub Actions against a deployed environment.
- Dual authentication. Exercises the API over both the static API key and OAuth2/JWT (Cognito access token on AWS; a self-minted RS256 JWT locally), with any test runnable under either auth without code changes.
- Multiple SUTs. One typed registry describes every deployment target (local + the four AWS partitions), each with declared capabilities that gate tests.
- Secrets never in the repo. All credentials are 1Password references resolved
at run time; the tree holds
op://pointers only. - Selectable scope. Tests carry a category (probe ⊆ sanity ⊆ acceptance ⊆ all, plus functional/stress/bug/extra) so a run loads exactly the intended slice.
- Governed flakiness. A quarantine mechanism with a compile-required ticket, an expiry, and a failure budget keeps known-bad tests visible without blocking.
- Reusable and extensible. The real goal is that the structure yields reusable elements that can be published and shared — across components and at the system level — and extended with new modules and scenarios. Packaging each non-test layer as a standalone unit is the mechanism that makes sharing a move-and-publish rather than a rewrite; it is not the goal itself.
Constraints
Section titled “Constraints”- Isolation. The subproject must stay isolated from the rest of the
operationsrepo — never touching the Gradle build, the Helm chart, or the deployable — so it can be separated out (into a shared library or its own repo) at any time. - No hardcoded local port. The local NodePort is dynamic; the base URL is discovered at run time.
- Direct-edit CHANGELOG. Every PR carries an entry (suite changes are usually
Fixed); the single per-repo version means a deployed tag identifies the exact suite revision that matches it. - en-US for all content and identifiers.
Assumptions
Section titled “Assumptions”- Each component serves its per-module OpenAPI publicly at
/v1/<module>/docs/openApi.json(no auth) — enough to generate the typed proxies. operationsaccepts either a static API key or a Cognito access token as the bearer (the id token is rejected).- Local deployments validate JWTs against a Caddy-served static JWKS
(
iss: http://caddy/), so a self-minted token needs no Cognito. - The SUT under test is reachable whenever tests or proxy generation run — an accepted, deliberate coupling (see the design contract check).
Supported Workflows
Section titled “Supported Workflows”These three workflows are the foundation the design serves. In all three, generate → compile → test is the spine, and compilation after generation is a cheap contract / backwards-compatibility check.
1. Local development — inner loop against a local cluster.
- Deploy the component to the local cluster.
- Run the suite with
SUT=local: generate the proxies from the locally published OpenAPI. - If it compiles, run the tests.
- On a compile or test failure, change the tests or the component (adding unit tests as needed) and loop from step 1 until development is complete.
2. Local verification — pre-merge check against dev (which runs origin/main
by construction; dev is shorthand for the current dev partition, the
alpha002-dev SUT key).
- Run the suite with
SUT=dev: generate from dev’s OpenAPI, compile, test. - If it fails, and the break is intended, record the intent in the CHANGELOG: a break in a pre-existing route → a major bump; an addition on a new route → a minor bump.
- Otherwise, fix the code or the tests until the run is clean (or the CHANGELOG decision converges).
3. CI run — automated gate after merge.
- A PR merges and the component deploys to
dev. - The suite is triggered with
SUT=dev: generate, compile, test. - On failure the deployment pipeline fails; the developer takes corrective action in a new PR.
Success Criteria
Section titled “Success Criteria”- A self-contained TypeScript suite in
operations/api-tests, at parity with the operations Bruno coverage, green against bothlocalanddev. - A single command (
make verify SUT=<name>) runs the full spine for any SUT, discovering the local base URL automatically. - Any test runs under api-key or OAuth with no code change; auth-specific tests gate themselves.
- The typed wire is generated from the SUT’s live OpenAPI and not committed, so a contract drift surfaces as a compile failure.
- The four package layers are a DAG enforced by the build, and each is structured for reuse — promotable to a shared library across components and at the system level.
- No secret values in the repository; capabilities and quarantine govern selection and flakiness.
See the design for how the parts realize these, and verification for how each is confirmed.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved