@saasicat/spec 1.0.0-rc.2 → 1.0.0-rc.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/acceptance/README.md +3 -3
- package/acceptance/mfa/totp-verify-good-and-bad-code.yaml +6 -6
- package/admin-api.openapi.yaml +328 -77
- package/cli-conventions.md +19 -19
- package/index.cjs +3 -0
- package/index.d.cts +3 -1
- package/index.d.ts +2 -0
- package/index.js +9 -1
- package/package.json +4 -2
- package/prisma-fragments/01-subscription.prisma +34 -47
- package/prisma-fragments/03-plan-versions.prisma +3 -4
- package/prisma-fragments/05-bundle.prisma +4 -5
- package/prisma-fragments/06-catalog-entries.prisma +24 -24
- package/prisma-fragments/07-promotion.prisma +2 -3
- package/prisma-fragments/08-subscription-contract.prisma +42 -5
- package/prisma-fragments/09-pending-registration.prisma +32 -27
- package/prisma-fragments/11-subscription-bundle.prisma +17 -0
- package/prisma-fragments/12-applied-settings.prisma +55 -0
- package/prisma-fragments/13-subscriber.prisma +94 -0
- package/prisma-fragments/14-payments.prisma +100 -0
- package/prisma-fragments/README.md +40 -22
- package/schemas/admin-manifest.schema.json +9 -2
- package/schemas/plan-catalog.schema.json +239 -18
- package/schemas/tenant-ledger.schema.json +236 -0
- package/sql/1.0-a-contract-names-its-subscriber.postgres.sql +383 -0
- package/sql/1.0-a-payment-method-is-a-gateway-reference.postgres.sql +177 -0
- package/sql/1.0-a-settings-change-carries-its-order.postgres.sql +73 -0
- package/sql/1.0-line-items-record-their-money.postgres.sql +134 -0
- package/sql/1.0-remove-project-key.postgres.sql +203 -0
- package/sql/1.0-the-applied-settings-are-recorded.postgres.sql +67 -0
- package/sql/constraints.postgres.sql +76 -0
- package/sql/reference-schema.postgres.sql +299 -77
package/README.md
CHANGED
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
# @saasicat/spec
|
|
2
2
|
|
|
3
|
+
## What this is
|
|
4
|
+
|
|
3
5
|
Language-neutral spec of the SaaS platform — JSON Schemas, OpenAPI and
|
|
4
6
|
acceptance test scenarios.
|
|
5
7
|
|
|
8
|
+
## What this is not
|
|
9
|
+
|
|
10
|
+
Not runnable code. JSON Schemas, an OpenAPI document, Prisma fragments and SQL
|
|
11
|
+
constraints — a contract any language can implement, which is why the reference
|
|
12
|
+
implementation is a separate package.
|
|
13
|
+
|
|
14
|
+
Not a migration tool. The fragments are merged into your own `schema.prisma`
|
|
15
|
+
by `saasicat schema apply`, and your Prisma or Drizzle migration flow takes it
|
|
16
|
+
from there.
|
|
17
|
+
|
|
18
|
+
## Entry points
|
|
19
|
+
|
|
20
|
+
| Entry | What is in it |
|
|
21
|
+
| ----------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
22
|
+
| `.` | The hand-written index: constants and helpers over the schemas. |
|
|
23
|
+
| `./schemas/*.json` | The JSON Schemas — the source of truth for every wire format. |
|
|
24
|
+
| `./prisma-fragments/*.prisma` | One fragment per table group, merged by `saasicat schema apply`. |
|
|
25
|
+
| `./prisma-fragments/` | The directory itself, for tooling that enumerates the fragments. |
|
|
26
|
+
| `./sql/*.sql` | The reference schema, the constraints Prisma cannot express, and the migrations a consumer applies by hand. |
|
|
27
|
+
|
|
6
28
|
## Contents
|
|
7
29
|
|
|
8
30
|
| File | Purpose |
|
|
@@ -11,6 +33,7 @@ acceptance test scenarios.
|
|
|
11
33
|
| `schemas/plan-catalog.schema.json` | App identity config format (`config/saas.yaml`) |
|
|
12
34
|
| `schemas/promo-code.schema.json` | Promo code format incl. redemption lifecycle |
|
|
13
35
|
| `schemas/audit-event.schema.json` | Audit log entry format |
|
|
36
|
+
| `schemas/tenant-ledger.schema.json` | A tenant's account: charges, payments, balance |
|
|
14
37
|
| `admin-api.openapi.yaml` | NORMATIVE REST contract of the SuperAdmin backend |
|
|
15
38
|
| `acceptance/` | HTTP test scenarios (stubs; runner planned) |
|
|
16
39
|
| `index.js` / `index.cjs` / `index.d.ts` | Re-exports for JS/TS consumers |
|
|
@@ -57,3 +80,10 @@ pnpm add @saasicat/spec
|
|
|
57
80
|
live in the DB, curated via the SuperAdmin UI.
|
|
58
81
|
- **`schemaVersion` is required** in every top-level schema. Major bumps
|
|
59
82
|
break — that is allowed, but must be documented in a migration note.
|
|
83
|
+
|
|
84
|
+
## Next
|
|
85
|
+
|
|
86
|
+
- [Data model](../../docs/explanation/data-model.md) — the tables the fragments declare
|
|
87
|
+
- [From capability to contract](../../docs/explanation/capability-to-contract.md) — what the schemas
|
|
88
|
+
describe
|
|
89
|
+
- [Codegen](../../docs/explanation/adr/0006-spec-to-types-codegen.md) — how types are derived from them
|
package/acceptance/README.md
CHANGED
|
@@ -10,10 +10,10 @@ document, but an executable set of guarantees.
|
|
|
10
10
|
Each scenario is a YAML file with the structure:
|
|
11
11
|
|
|
12
12
|
```yaml
|
|
13
|
-
scenario: '
|
|
13
|
+
scenario: 'What the behaviour is, in one sentence'
|
|
14
14
|
description: |
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
The longer version — what this holds, and why it matters.
|
|
16
|
+
Point at the SPEC section, or at the question still open.
|
|
17
17
|
|
|
18
18
|
setup: # state setup via Admin API calls
|
|
19
19
|
- createTenant: { slug: '...', email: '...' }
|
|
@@ -18,26 +18,26 @@ cases:
|
|
|
18
18
|
- name: 'valid TOTP code'
|
|
19
19
|
request:
|
|
20
20
|
method: POST
|
|
21
|
-
path: /api/v1/admin/tenants/test-
|
|
21
|
+
path: /api/v1/admin/tenants/test-tenant/suspend
|
|
22
22
|
auth: { as: 'super@platform.example' }
|
|
23
23
|
headers:
|
|
24
24
|
X-Mfa-Code: '{{generateTotpFor: super@platform.example}}'
|
|
25
25
|
body: { reason: 'test reason' }
|
|
26
26
|
pre:
|
|
27
|
-
- createTenant: { slug: 'test-
|
|
27
|
+
- createTenant: { slug: 'test-tenant', email: 'x@test-tenant.example' }
|
|
28
28
|
then:
|
|
29
29
|
status: 200
|
|
30
30
|
|
|
31
31
|
- name: 'invalid TOTP code'
|
|
32
32
|
request:
|
|
33
33
|
method: POST
|
|
34
|
-
path: /api/v1/admin/tenants/test-
|
|
34
|
+
path: /api/v1/admin/tenants/test-tenant/suspend
|
|
35
35
|
auth: { as: 'super@platform.example' }
|
|
36
36
|
headers:
|
|
37
37
|
X-Mfa-Code: '000000'
|
|
38
38
|
body: { reason: 'test reason' }
|
|
39
39
|
pre:
|
|
40
|
-
- createTenant: { slug: 'test-
|
|
40
|
+
- createTenant: { slug: 'test-tenant-2', email: 'y@test-tenant-2.example' }
|
|
41
41
|
then:
|
|
42
42
|
status: 401
|
|
43
43
|
body:
|
|
@@ -46,11 +46,11 @@ cases:
|
|
|
46
46
|
- name: 'missing TOTP header'
|
|
47
47
|
request:
|
|
48
48
|
method: POST
|
|
49
|
-
path: /api/v1/admin/tenants/test-
|
|
49
|
+
path: /api/v1/admin/tenants/test-tenant-3/suspend
|
|
50
50
|
auth: { as: 'super@platform.example' }
|
|
51
51
|
body: { reason: 'test reason' }
|
|
52
52
|
pre:
|
|
53
|
-
- createTenant: { slug: 'test-
|
|
53
|
+
- createTenant: { slug: 'test-tenant-3', email: 'z@test-tenant-3.example' }
|
|
54
54
|
then:
|
|
55
55
|
status: 401
|
|
56
56
|
body:
|