@stratum-hq/core 1.4.0 → 1.5.1
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 +10 -8
- package/dist/types/region.d.ts +2 -2
- package/dist/types/region.d.ts.map +1 -1
- package/dist/types/region.js +18 -2
- package/dist/types/region.js.map +1 -1
- package/dist/types/usage.d.ts +1 -1
- package/dist/types/usage.js +1 -1
- package/dist/utils/ancestry.d.ts +1 -1
- package/dist/utils/ancestry.js +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @stratum-hq/core
|
|
2
2
|
|
|
3
|
-
Shared foundation for all [Stratum](https://github.com/stratum-hq/Stratum) packages
|
|
3
|
+
Shared foundation for all [Stratum](https://github.com/stratum-hq/Stratum) packages: TypeScript types, Zod validation schemas, error classes, utility functions, and constants. Every other Stratum package depends on it.
|
|
4
|
+
|
|
5
|
+
Read the documentation at [docs.stratum-hq.org/packages/core](https://docs.stratum-hq.org/packages/core/).
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -27,7 +29,7 @@ import {
|
|
|
27
29
|
IsolationStrategy.SHARED_RLS; // "SHARED_RLS"
|
|
28
30
|
PermissionMode.LOCKED; // "LOCKED"
|
|
29
31
|
|
|
30
|
-
// Zod schemas
|
|
32
|
+
// Zod schemas: validate untrusted input
|
|
31
33
|
SlugSchema.parse("acme_corp"); // passes
|
|
32
34
|
SlugSchema.parse("INVALID"); // throws ZodError
|
|
33
35
|
|
|
@@ -44,12 +46,12 @@ try {
|
|
|
44
46
|
|
|
45
47
|
## What's Exported
|
|
46
48
|
|
|
47
|
-
- **Types
|
|
48
|
-
- **Enums
|
|
49
|
-
- **Zod schemas
|
|
50
|
-
- **Ancestry utilities
|
|
51
|
-
- **Errors
|
|
52
|
-
- **Constants
|
|
49
|
+
- **Types**: `TenantNode`, `TenantContext`, `ResolvedConfigEntry`, `ResolvedPermission`, `CreateTenantInput`, `SetConfigInput`, `AuditEntry`, `ConsentRecord`, `Region`, `AbacPolicy`, and more.
|
|
50
|
+
- **Enums**: `IsolationStrategy` (`SHARED_RLS`, `SCHEMA_PER_TENANT`, `DB_PER_TENANT`), `PermissionMode` (`LOCKED`, `INHERITED`, `DELEGATED`), `RevocationMode` (`CASCADE`, `SOFT`, `PERMANENT`), `TenantStatus`.
|
|
51
|
+
- **Zod schemas**: `SlugSchema`, `UUIDSchema`, `PaginationSchema`, `CreateTenantInputSchema`, `SetConfigInputSchema`, `CreatePermissionInputSchema`, `AuditLogQuerySchema`, and their input types.
|
|
52
|
+
- **Ancestry utilities**: `buildAncestryPath`, `parseAncestryPath`, `getDepth`, `isAncestorOf`, `isDescendantOf`, `getAncestorIds`.
|
|
53
|
+
- **Errors**: `StratumError` plus `TenantNotFoundError`, `ConfigLockedError`, `PermissionRevocationDeniedError`, `IsolationViolationError`, `UnauthorizedError`, `ForbiddenError`, and others.
|
|
54
|
+
- **Constants**: `MAX_SLUG_LENGTH` (63), `DEFAULT_CACHE_TTL_MS`, `DEFAULT_PAGE_SIZE`, `MAX_PAGE_SIZE`, `API_KEY_PREFIX`, `TENANT_HEADER`.
|
|
53
55
|
|
|
54
56
|
## Links
|
|
55
57
|
|
package/dist/types/region.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export type Region = z.infer<typeof RegionSchema>;
|
|
|
42
42
|
export declare const CreateRegionInputSchema: z.ZodObject<{
|
|
43
43
|
display_name: z.ZodString;
|
|
44
44
|
slug: z.ZodString;
|
|
45
|
-
control_plane_url: z.ZodOptional<z.ZodString
|
|
45
|
+
control_plane_url: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
46
46
|
is_primary: z.ZodOptional<z.ZodBoolean>;
|
|
47
47
|
status: z.ZodOptional<z.ZodEnum<["active", "draining", "inactive"]>>;
|
|
48
48
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -64,7 +64,7 @@ export declare const CreateRegionInputSchema: z.ZodObject<{
|
|
|
64
64
|
export type CreateRegionInput = z.input<typeof CreateRegionInputSchema>;
|
|
65
65
|
export declare const UpdateRegionInputSchema: z.ZodObject<{
|
|
66
66
|
display_name: z.ZodOptional<z.ZodString>;
|
|
67
|
-
control_plane_url: z.ZodOptional<z.ZodNullable<z.ZodString
|
|
67
|
+
control_plane_url: z.ZodOptional<z.ZodNullable<z.ZodEffects<z.ZodString, string, string>>>;
|
|
68
68
|
status: z.ZodOptional<z.ZodEnum<["active", "draining", "inactive"]>>;
|
|
69
69
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
70
70
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../src/types/region.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;CAIf,CAAC;
|
|
1
|
+
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../src/types/region.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;CAIf,CAAC;AAoBX,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWvB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;EAOlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;EAKlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,wBAAwB;;;;;;EAEnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
package/dist/types/region.js
CHANGED
|
@@ -7,6 +7,22 @@ exports.RegionStatus = {
|
|
|
7
7
|
DRAINING: "draining",
|
|
8
8
|
INACTIVE: "inactive",
|
|
9
9
|
};
|
|
10
|
+
// A control-plane URL must be http or https and must not embed credentials: it
|
|
11
|
+
// is stored in plaintext, returned by the API and recorded in audit state.
|
|
12
|
+
const ControlPlaneUrlSchema = zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.url()
|
|
15
|
+
.refine((value) => {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = new URL(value);
|
|
18
|
+
return ((parsed.protocol === "http:" || parsed.protocol === "https:") &&
|
|
19
|
+
parsed.username === "" &&
|
|
20
|
+
parsed.password === "");
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}, "control_plane_url must be an http or https URL without credentials");
|
|
10
26
|
exports.RegionSchema = zod_1.z.object({
|
|
11
27
|
id: zod_1.z.string().uuid(),
|
|
12
28
|
display_name: zod_1.z.string().min(1),
|
|
@@ -22,14 +38,14 @@ exports.RegionSchema = zod_1.z.object({
|
|
|
22
38
|
exports.CreateRegionInputSchema = zod_1.z.object({
|
|
23
39
|
display_name: zod_1.z.string().min(1),
|
|
24
40
|
slug: zod_1.z.string().regex(/^[a-z][a-z0-9_]{0,62}$/),
|
|
25
|
-
control_plane_url:
|
|
41
|
+
control_plane_url: ControlPlaneUrlSchema.optional(),
|
|
26
42
|
is_primary: zod_1.z.boolean().optional(),
|
|
27
43
|
status: zod_1.z.enum(["active", "draining", "inactive"]).optional(),
|
|
28
44
|
metadata: zod_1.z.record(zod_1.z.unknown()).optional(),
|
|
29
45
|
});
|
|
30
46
|
exports.UpdateRegionInputSchema = zod_1.z.object({
|
|
31
47
|
display_name: zod_1.z.string().min(1).optional(),
|
|
32
|
-
control_plane_url:
|
|
48
|
+
control_plane_url: ControlPlaneUrlSchema.nullable().optional(),
|
|
33
49
|
status: zod_1.z.enum(["active", "draining", "inactive"]).optional(),
|
|
34
50
|
metadata: zod_1.z.record(zod_1.z.unknown()).optional(),
|
|
35
51
|
});
|
package/dist/types/region.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../src/types/region.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAEX,QAAA,YAAY,GAAG;IAC1B,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;CACZ,CAAC;
|
|
1
|
+
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../src/types/region.ts"],"names":[],"mappings":"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"}
|
package/dist/types/usage.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
* Input to record a single usage event for a tenant.
|
|
4
4
|
*
|
|
5
5
|
* `quantity` defaults to 1 (one countable unit) and must be a non-negative
|
|
6
|
-
* integer
|
|
6
|
+
* integer: metering counts up; credits / adjustments are out of scope.
|
|
7
7
|
* `occurred_at` is when the usage happened (ISO 8601); it defaults to insert
|
|
8
8
|
* time and is the timestamp aggregation windows filter on, so a back-dated
|
|
9
9
|
* import still lands in the right billing window. `idempotency_key`, when
|
package/dist/types/usage.js
CHANGED
|
@@ -7,7 +7,7 @@ const timestamptz_js_1 = require("../utils/timestamptz.js");
|
|
|
7
7
|
* Input to record a single usage event for a tenant.
|
|
8
8
|
*
|
|
9
9
|
* `quantity` defaults to 1 (one countable unit) and must be a non-negative
|
|
10
|
-
* integer
|
|
10
|
+
* integer: metering counts up; credits / adjustments are out of scope.
|
|
11
11
|
* `occurred_at` is when the usage happened (ISO 8601); it defaults to insert
|
|
12
12
|
* time and is the timestamp aggregation windows filter on, so a back-dated
|
|
13
13
|
* import still lands in the right billing window. `idempotency_key`, when
|
package/dist/utils/ancestry.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export declare function appendToPath(parentPath: string, childId: string): strin
|
|
|
50
50
|
*/
|
|
51
51
|
export declare function getAncestorIds(path: string): string[];
|
|
52
52
|
/**
|
|
53
|
-
* Get the last ID in an ancestry path
|
|
53
|
+
* Get the last ID in an ancestry path: the tenant's direct parent
|
|
54
54
|
* (ancestry paths exclude self). Returns null for a root tenant ("/").
|
|
55
55
|
*/
|
|
56
56
|
export declare function getSelfId(path: string): string | null;
|
package/dist/utils/ancestry.js
CHANGED
|
@@ -92,7 +92,7 @@ function getAncestorIds(path) {
|
|
|
92
92
|
return parseAncestryPath(path);
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
|
-
* Get the last ID in an ancestry path
|
|
95
|
+
* Get the last ID in an ancestry path: the tenant's direct parent
|
|
96
96
|
* (ancestry paths exclude self). Returns null for a root tenant ("/").
|
|
97
97
|
*/
|
|
98
98
|
function getSelfId(path) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratum-hq/core",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Shared types, Zod schemas, and errors for the Stratum multi-tenancy packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"multi-tenancy",
|
|
7
|
+
"multitenancy",
|
|
7
8
|
"multi-tenant",
|
|
8
9
|
"saas",
|
|
9
10
|
"tenant",
|
|
11
|
+
"tenant-isolation",
|
|
12
|
+
"zod",
|
|
10
13
|
"typescript",
|
|
11
14
|
"validation",
|
|
12
15
|
"schemas",
|
|
@@ -45,7 +48,7 @@
|
|
|
45
48
|
},
|
|
46
49
|
"license": "MIT",
|
|
47
50
|
"author": "Christian Crank",
|
|
48
|
-
"homepage": "https://
|
|
51
|
+
"homepage": "https://docs.stratum-hq.org/packages/core/",
|
|
49
52
|
"bugs": "https://github.com/stratum-hq/Stratum/issues",
|
|
50
53
|
"engines": {
|
|
51
54
|
"node": ">=20.0.0"
|