Skip to content

Commit 107dbfb

Browse files
midagedevclaude
andcommitted
Document billing workspaces in architecture and specs
Reflect the new isolated-workspace feature across the design docs and the product spec: testing isolation guidance, the storage architecture note, functional requirement FR-010, non-functional requirement NFR-008, the API contract Workspaces section, the data-model scoping note, and tasks T147. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c1346f7 commit 107dbfb

6 files changed

Lines changed: 47 additions & 1 deletion

File tree

‎docs/ARCHITECTURE.md‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,14 @@ Initial default:
6767
- SQLite for local app state
6868
- in-memory option for unit tests
6969

70-
Tables:
70+
One running server can host several isolated billing datasets. The implicit
71+
`default` workspace is backed by the configured `database_url`; each named
72+
workspace (selected per request via the `X-Billtap-Workspace` header or
73+
`workspace` query parameter) opens its own SQLite database lazily under a
74+
sibling `workspaces/` directory and gets an independent API handler, so its
75+
billing state, webhooks, idempotency keys, and test clocks stay isolated.
76+
77+
Tables (per workspace):
7178

7279
- customers
7380
- products

‎docs/TESTING.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ Fixture ergonomics for integration tests:
8181
- assert expected objects through `POST /api/fixtures/assert`
8282
- keep fixture IDs stable for customer, product, and price setup
8383
- use fixture `runId`, `namespace`, `tenantId`, and `ref` metadata to isolate repeated local/CI runs
84+
- for stronger isolation, run parallel suites against separate Billtap
85+
workspaces instead of restarting the server between sets: send
86+
`X-Billtap-Workspace: <name>` (or `?workspace=<name>`) so each suite gets an
87+
independent dataset, while unselected requests keep using the `default`
88+
workspace; `GET /workspaces` lists what exists
8489

8590
Integration diagnostics for failed app runs:
8691

‎specs/000-product/contracts/api.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@ Process health.
1616

1717
Storage and worker readiness.
1818

19+
## Workspaces
20+
21+
One running server can host several isolated billing datasets. Every `/v1`
22+
and `/api` request resolves a workspace before dispatch:
23+
24+
- A request with no selector uses the `default` workspace, backed by the
25+
configured `database_url`. This keeps existing integrations unchanged.
26+
- A request may select a named workspace with the `X-Billtap-Workspace`
27+
request header or the `workspace` query parameter. Named workspaces are
28+
created on first use, have their own storage, and are isolated from each
29+
other and from `default`.
30+
- The resolved workspace name is returned on the `X-Billtap-Workspace`
31+
response header. An invalid workspace name returns `400`.
32+
33+
### `GET /workspaces`
34+
35+
Lists known workspaces (the default, any opened this session, and any whose
36+
database file already exists). Returns a `list` envelope of `workspace`
37+
objects with `name` and `is_default`.
38+
1939
## Stripe-like API
2040

2141
### Customers

‎specs/000-product/data-model.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Data Model
22

3+
All entities below are scoped to a single workspace. A server hosts the
4+
implicit `default` workspace plus any named workspaces; each workspace has its
5+
own isolated store, so the same entity id may exist independently in different
6+
workspaces. Workspaces are an instance-level partition and are not themselves
7+
persisted rows — see `contracts/api.md` for selection and listing.
8+
39
## Customer
410

511
- id

‎specs/000-product/spec.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ Acceptance criteria:
117117
- FR-007: Create, retrieve, confirm, fail, and list payment intents.
118118
- FR-008: Create, retrieve, update, delete, and list webhook endpoints.
119119
- FR-009: Create, retrieve, and list events.
120+
- FR-010: Serve isolated billing workspaces from one running server. Requests
121+
with no workspace selector use the backward-compatible `default` workspace;
122+
a request may select a named workspace via the `X-Billtap-Workspace` header
123+
or `workspace` query parameter to get an independent dataset, and the known
124+
workspaces are listable.
120125

121126
### Hosted UI
122127

@@ -177,6 +182,8 @@ Acceptance criteria:
177182
- NFR-005: No real card data is stored.
178183
- NFR-006: Contract behavior is fixture-backed.
179184
- NFR-007: Profile-specific behavior is fixture-backed and does not require production payment credentials.
185+
- NFR-008: Named workspaces are isolated at the storage boundary so parallel
186+
test suites do not need a server restart or shared-state reset between runs.
180187

181188
## Non-Goals
182189

‎specs/000-product/tasks.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ Gate:
269269
- [x] T144 Capture the public simulation capacity backlog for regression-driven fixture and scenario expansion
270270
- [x] T145 Expand customer history, subscription pause/resume, and payment-method attach/detach simulation routes
271271
- [x] T146 Add browser-facing public base path and forwarded-prefix support
272+
- [x] T147 Add isolated billing workspaces selectable per request so parallel test suites share one server
272273

273274
Suggested agents:
274275

0 commit comments

Comments
 (0)