You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guide/architecture.md
+10-2Lines changed: 10 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -179,6 +179,12 @@ Both encryption and decryption support streaming (`ReadableStream`/`WritableStre
179
179
|`GET`|`/v2/irma/key/{timestamp}`| Retrieve a User Secret Key (USK). Requires `Authorization: Bearer <jwt>`. The timestamp must match the one embedded in the ciphertext. |
180
180
|`POST`|`/v2/irma/sign/key`| Retrieve signing keys. Authenticate with either an API key (`Bearer PG-...`) or a Yivi JWT. |
181
181
182
+
#### API Key Validation
183
+
184
+
| Method | Endpoint | Description |
185
+
|---|---|---|
186
+
|`GET`|`/v2/api-key/validate`| Confirm a `PG-…` API key is valid and return `{ tenant_id, organisation_name }`. Requires `Authorization: Bearer PG-…`. Used by sibling services (e.g. Cryptify) that need to gate per-tenant behaviour on a validated key without going through signing-key issuance. Validates against the shared `business_api_keys` table; only registered when the PKG is configured with a database pool. |
187
+
182
188
#### Health
183
189
184
190
| Method | Endpoint | Description |
@@ -194,11 +200,13 @@ The key issuance endpoints require a valid `Authorization: Bearer <jwt>` header.
194
200
195
201
| Method | Endpoint | Description |
196
202
|---|---|---|
197
-
|`POST`|`/fileupload/init`| Initialize a file upload. Returns a UUID and upload token. |
198
-
|`PUT`|`/fileupload/{uuid}`| Upload a chunk. Uses `Content-Range` headers for offset tracking. Requires `cryptifytoken` header. |
203
+
|`POST`|`/fileupload/init`| Initialize a file upload. Returns a UUID and upload token. Optional `Authorization: Bearer PG-…` unlocks the higher upload-quota tier; Cryptify forwards the bearer to PKG's `/v2/api-key/validate` and uses the returned tenant id for rolling-window accounting. |
204
+
|`PUT`|`/fileupload/{uuid}`| Upload a chunk. Uses `Content-Range` headers for offset tracking. Requires `cryptifytoken` header. Carries the same `Authorization` bearer on each chunk as `init`. |
199
205
|`POST`|`/fileupload/finalize/{uuid}`| Finalize the upload after all chunks are sent. |
200
206
|`GET`|`/filedownload/{uuid}`| Download an encrypted file as a stream. |
201
207
208
+
See [Upload limits](/repos/cryptify#upload-limits) and [Authentication for the higher tier](/repos/cryptify#authentication-for-the-higher-tier) on the Cryptify page for the tier breakdown and PKG-unreachable behaviour (503 vs. 413).
Copy file name to clipboardExpand all lines: docs/guide/concepts.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -194,6 +194,8 @@ The sender proves their email address via Yivi, just like the recipient does dur
194
194
### API key signing (PostGuard for Business)
195
195
For automated or server-side encryption, an API key replaces the Yivi step. The organization operating the sender's application is trusted to authenticate the sender through its own mechanisms.
196
196
197
+
The same API key also unlocks the higher upload-quota tier on Cryptify (100 GB/upload, 100 GB rolling) when the encrypted payload is delivered through Cryptify. The SDK attaches `Authorization: Bearer <apiKey>` to every upload request automatically; Cryptify forwards the bearer to PKG for validation. See [Upload limits](/repos/cryptify#upload-limits) on the Cryptify page.
198
+
197
199
When the recipient decrypts, the SDK returns a `sender` field with type `FriendlySender` containing the verified identity attributes of the sender. The Thunderbird addon extracts sender attributes to build identity badges:
| Per-chunk size |`chunk_size` from config (default 5 MB) | same as anonymous| Bigger chunks are rejected with `400 Bad Request`. |
44
+
| Per-chunk size |`chunk_size` from config (default 5 MB) | same as default| Bigger chunks are rejected with `400 Bad Request`. |
45
45
| Per-upload size | 5 GB | 100 GB | Total bytes for a single upload session. |
46
-
| Rolling window total | 5 GB per 14 days | 100 GB per 14 days |Sum of all uploads from the same sender email in the trailing 14 days. |
46
+
| Rolling window total | 5 GB per 14 days | 100 GB per 14 days |Default tier accounts per sender email; API-key tier accounts per tenant id. |
47
47
48
-
A sender is identified by the email attribute disclosed in the encrypted envelope's signature. The rolling window only counts finalized uploads.
48
+
The default tier identifies the sender by the email attribute disclosed in the encrypted envelope's signature. The API-key tier accounts on the validated tenant id (`api-key:<organizations.id>`) so a single tenant cannot evade quota by varying sender attributes. See [Authentication for the higher tier](#authentication-for-the-higher-tier) below.
49
+
50
+
The rolling window only counts finalized uploads.
49
51
50
52
When a request would push the sender over the per-upload or the rolling-window limit, the server responds with `413 Payload Too Large` and a JSON body:
51
53
@@ -61,10 +63,31 @@ When a request would push the sender over the per-upload or the rolling-window l
61
63
62
64
`limit` is either `"per_upload"` or `"rolling_window"`. `resets_at` is an RFC 3339 timestamp for when the oldest counted upload expires from the rolling window. It is `null` for `per_upload` rejections, since the per-upload limit does not reset.
63
65
64
-
`GET /usage` returns the current state for the authenticated sender, including `used_bytes`, `limit_bytes`, `per_upload_limit_bytes`, `window_days`, and `resets_at`.
66
+
`GET /usage` returns the current state for the authenticated sender, including `used_bytes`, `limit_bytes`, `per_upload_limit_bytes`, `window_days`, and `resets_at`. When the request includes a validated `Authorization: Bearer PG-…`, the response describes the per-tenant bucket (`api-key:<tenant>`); otherwise it describes the per-email bucket.
Callers unlock the API-key tier by sending `Authorization: Bearer PG-…` on every upload request (`init`, each chunk PUT, and `finalize`). The key is a PostGuard for Business API key issued through the [postguard-business](/repos/postguard-business) portal.
73
+
74
+
Cryptify itself does not own the key allowlist. On `init` it forwards the bearer to PKG's `GET /v2/api-key/validate`, which authenticates against the shared `business_api_keys` table and returns the tenant id (`organizations.id`). Cryptify uses that id for tier selection and as the rolling-window accounting key. Validation runs only at `init` — once the upload session is established, the tier and accounting key are fixed for its lifetime.
75
+
76
+
| Validation outcome | Tier applied | Behaviour on cap exceeded |
77
+
|---|---|---|
78
+
| No `Authorization` header / non-PG bearer | Default |`413 Payload Too Large`|
79
+
| PKG returns `2xx` with tenant id | API-key |`413 Payload Too Large` (at 100 GB) |
80
+
| PKG returns `401`/`403` (unknown or expired key) | Default |`413 Payload Too Large`|
81
+
| PKG unreachable for the full retry budget | Default + warning |**`503 Service Unavailable`** when the upload exceeds the default 5 GB cap; `413` otherwise behaviour matches default |
82
+
83
+
The PKG retry budget at `init` is 30 seconds with exponential backoff (250 ms → 5 s ceiling). Authoritative responses (`2xx` with body, `401`, `403`) short-circuit the retry loop. Connection errors and `5xx` are retried until the budget is exhausted.
84
+
85
+
The 503 response distinguishes "we couldn't tell whether you should have gotten the higher tier" from the regular 413 ("you're over your tier's cap"). Smaller uploads degrade silently to the default tier with a warning logged on the server, so transient PKG outages don't block uploads that would have fit anyway.
86
+
87
+
The legacy `X-Api-Key` header is no longer recognised; older clients that still send it are treated as default tier.
Cryptify exposes a file upload/download API. An OpenAPI 3.0 specification is available in `api-description.yaml` in the repository root. The main endpoints:
0 commit comments