@antelopejs/interface-dms 0.7.2 → 0.7.4
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/CHANGELOG.md +52 -0
- package/dist/base/block-registry/index.d.ts +1 -0
- package/dist/base/block-registry/index.js +1 -0
- package/dist/base/block-registry/index.js.map +1 -1
- package/dist/base/block-registry/presentation.d.ts +21 -0
- package/dist/base/block-registry/presentation.js +108 -0
- package/dist/base/block-registry/presentation.js.map +1 -0
- package/dist/base/placeholder.js +2 -2
- package/dist/base/placeholder.js.map +1 -1
- package/dist/data-controllers/members.d.ts +2 -2
- package/dist/data-controllers/members.js +15 -8
- package/dist/data-controllers/members.js.map +1 -1
- package/dist/db/internal/tenantLifecycle.model.d.ts +4 -0
- package/dist/db/internal/tenantLifecycle.model.js +23 -0
- package/dist/db/internal/tenantLifecycle.model.js.map +1 -1
- package/dist/db/internal/tenantLifecycle.table.d.ts +1 -0
- package/dist/db/internal/tenantLifecycle.table.js +4 -0
- package/dist/db/internal/tenantLifecycle.table.js.map +1 -1
- package/dist/hooks.d.ts +11 -0
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/internal/invite-membership.js +7 -0
- package/dist/internal/invite-membership.js.map +1 -1
- package/dist/internal/tenant-ownership.js +9 -0
- package/dist/internal/tenant-ownership.js.map +1 -1
- package/dist/tenant-access.d.ts +15 -0
- package/dist/tenant-access.js +11 -1
- package/dist/tenant-access.js.map +1 -1
- package/dist/tenant-lifecycle.d.ts +27 -0
- package/dist/tenant-lifecycle.js +35 -0
- package/dist/tenant-lifecycle.js.map +1 -1
- package/dist/tenant-ownership.js +18 -1
- package/dist/tenant-ownership.js.map +1 -1
- package/docs/1.core/2.pages-and-modules.md +2 -0
- package/docs/1.core/5.tenancy.md +18 -1
- package/docs/1.core/7.hooks.md +3 -0
- package/docs/3.base/1.introduction.md +1 -1
- package/docs/3.base/6.layout.md +7 -1
- package/docs/4.notifications/1.introduction.md +2 -0
- package/docs/4.notifications/2.categories-and-subjects.md +2 -0
- package/docs/4.notifications/3.sending.md +2 -0
- package/docs/5.html-render/1.introduction.md +14 -0
- package/docs/5.html-render/2.built-in-emails.md +50 -0
- package/docs/images/emails-admin-invite.png +0 -0
- package/docs/images/emails-change-notice.png +0 -0
- package/docs/images/emails-change-verification.png +0 -0
- package/docs/images/emails-digest-logo-dark.png +0 -0
- package/docs/images/emails-digest-logo-light.png +0 -0
- package/docs/images/emails-digest.png +0 -0
- package/docs/images/emails-export-partial.png +0 -0
- package/docs/images/emails-export-ready.png +0 -0
- package/docs/images/emails-reset-password.png +0 -0
- package/docs/images/emails-two-factor.png +0 -0
- package/docs/images/emails-user-validation.png +0 -0
- package/docs/index.md +9 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.7.4
|
|
4
|
+
|
|
5
|
+
[compare changes](https://github.com/AntelopeJS/dms/compare/interface-v0.7.3...v0.7.4)
|
|
6
|
+
|
|
7
|
+
### 🚀 Enhancements
|
|
8
|
+
|
|
9
|
+
- **tenant-lifecycle:** Pause producer admission and evaluate every tenant access gate ([#366](https://github.com/AntelopeJS/dms/pull/366))
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- **deps:** Require the shared preview presentation contract ([#340](https://github.com/AntelopeJS/dms/pull/340))
|
|
14
|
+
- **frontend:** Read the onboarding status and permissions through the data layer ([#357](https://github.com/AntelopeJS/dms/pull/357))
|
|
15
|
+
|
|
16
|
+
### 🏡 Chore
|
|
17
|
+
|
|
18
|
+
- **release:** @antelopejs/dms v0.9.5 ([a8e395eb](https://github.com/AntelopeJS/dms/commit/a8e395eb))
|
|
19
|
+
|
|
20
|
+
### ❤️ Contributors
|
|
21
|
+
|
|
22
|
+
- Antony Rizzitelli <rizzitelli.antony@pm.me>
|
|
23
|
+
- Alessandro Aloisio ([@alessaloisio](http://github.com/alessaloisio))
|
|
24
|
+
|
|
25
|
+
## v0.7.3
|
|
26
|
+
|
|
27
|
+
[compare changes](https://github.com/AntelopeJS/dms/compare/interface-v0.7.2...v0.7.3)
|
|
28
|
+
|
|
29
|
+
### 🚀 Enhancements
|
|
30
|
+
|
|
31
|
+
- **preview:** Share simple options and document real outcomes ([#339](https://github.com/AntelopeJS/dms/pull/339))
|
|
32
|
+
|
|
33
|
+
### 🩹 Fixes
|
|
34
|
+
|
|
35
|
+
- **docs:** Use a sandbox-compatible temporary build database ([#326](https://github.com/AntelopeJS/dms/pull/326))
|
|
36
|
+
- Install DMS frontend with the root workspace ([#322](https://github.com/AntelopeJS/dms/pull/322))
|
|
37
|
+
- **modules:** Top-align card content and place readouts below descriptions ([#328](https://github.com/AntelopeJS/dms/pull/328))
|
|
38
|
+
- **modules:** Reuse registered names in the store ([#330](https://github.com/AntelopeJS/dms/pull/330))
|
|
39
|
+
- **playground:** Use the workspace CLI and compatible core interface ([#331](https://github.com/AntelopeJS/dms/pull/331))
|
|
40
|
+
|
|
41
|
+
### 📖 Documentation
|
|
42
|
+
|
|
43
|
+
- Create the DMS demo through the CLI in quickstart ([#327](https://github.com/AntelopeJS/dms/pull/327))
|
|
44
|
+
|
|
45
|
+
### 🏡 Chore
|
|
46
|
+
|
|
47
|
+
- **release:** @antelopejs/dms v0.9.3 ([1aaf5404](https://github.com/AntelopeJS/dms/commit/1aaf5404))
|
|
48
|
+
- **docs:** Capture temporary MongoDB startup diagnostics ([#325](https://github.com/AntelopeJS/dms/pull/325))
|
|
49
|
+
- **playground:** Refresh compatible dependencies ([#329](https://github.com/AntelopeJS/dms/pull/329))
|
|
50
|
+
|
|
51
|
+
### ❤️ Contributors
|
|
52
|
+
|
|
53
|
+
- Antony Rizzitelli <rizzitelli.antony@pm.me>
|
|
54
|
+
|
|
3
55
|
## v0.7.2
|
|
4
56
|
|
|
5
57
|
[compare changes](https://github.com/AntelopeJS/dms/compare/interface-v0.7.1...v0.7.2)
|
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./helpers"), exports);
|
|
18
|
+
__exportStar(require("./presentation"), exports);
|
|
18
19
|
__exportStar(require("./registry"), exports);
|
|
19
20
|
__exportStar(require("./types"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/base/block-registry/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,6CAA2B;AAC3B,0CAAwB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/base/block-registry/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,iDAA+B;AAC/B,6CAA2B;AAC3B,0CAAwB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BlockOptionUi, BlockTypeDescriptor } from "./types";
|
|
2
|
+
/** The hints needed to decide whether an editor offers an option in simple mode. */
|
|
3
|
+
export interface SimpleBlockOption {
|
|
4
|
+
ui?: Pick<BlockOptionUi, "hidden" | "advanced" | "derivedFrom"> & {
|
|
5
|
+
group?: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
/** Shared simple-mode policy; data binding remains available in the builder. */
|
|
9
|
+
export declare function IsSimpleBlockOption(option: SimpleBlockOption): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Dotted paths a standalone preview can edit without replacing data or opaque
|
|
12
|
+
* values. Objects are descended into, never offered as JSON. Only enum arrays
|
|
13
|
+
* in presentation/behavior groups and closed-key scalar records are editable
|
|
14
|
+
* collections; rows, slots and other structural collections remain fixed.
|
|
15
|
+
* Scalar unions have typed controls; a rich union with an explicit scalar
|
|
16
|
+
* widget (e.g. translated text or chart color) offers that scalar only.
|
|
17
|
+
*
|
|
18
|
+
* Fixed factory options exclude their entire top-level subtree. The returned
|
|
19
|
+
* paths reference `config`; consumers must not keep another copy of the schema.
|
|
20
|
+
*/
|
|
21
|
+
export declare function BlockPresentationPaths(descriptor: Pick<BlockTypeDescriptor, "config" | "fixedOptions">): string[];
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IsSimpleBlockOption = IsSimpleBlockOption;
|
|
4
|
+
exports.BlockPresentationPaths = BlockPresentationPaths;
|
|
5
|
+
/** Shared simple-mode policy; data binding remains available in the builder. */
|
|
6
|
+
function IsSimpleBlockOption(option) {
|
|
7
|
+
const ui = option.ui;
|
|
8
|
+
return (!ui?.hidden && !ui?.advanced && !ui?.derivedFrom && ui?.group !== "advanced");
|
|
9
|
+
}
|
|
10
|
+
const PRESENTATION_WIDGETS = new Set([
|
|
11
|
+
"text",
|
|
12
|
+
"textarea",
|
|
13
|
+
"number",
|
|
14
|
+
"range",
|
|
15
|
+
"switch",
|
|
16
|
+
"select",
|
|
17
|
+
"segmented",
|
|
18
|
+
"icon",
|
|
19
|
+
"color",
|
|
20
|
+
"url",
|
|
21
|
+
]);
|
|
22
|
+
function isPresentation(option) {
|
|
23
|
+
return (IsSimpleBlockOption(option) &&
|
|
24
|
+
option.ui?.group !== "data" &&
|
|
25
|
+
!option.truncated &&
|
|
26
|
+
(!option.ui?.widget || PRESENTATION_WIDGETS.has(option.ui.widget)));
|
|
27
|
+
}
|
|
28
|
+
// A scalar widget can replace a union's structured value, so a restricted
|
|
29
|
+
// descendant in any branch forbids offering that parent too.
|
|
30
|
+
function hasRestrictedHints(option) {
|
|
31
|
+
if (!IsSimpleBlockOption(option) ||
|
|
32
|
+
option.ui?.group === "data" ||
|
|
33
|
+
(option.ui?.widget && !PRESENTATION_WIDGETS.has(option.ui.widget)))
|
|
34
|
+
return true;
|
|
35
|
+
const children = [
|
|
36
|
+
...Object.values(option.properties ?? {}),
|
|
37
|
+
...[option.items, option.values, option.keys].filter((child) => !!child),
|
|
38
|
+
...(option.oneOf ?? []),
|
|
39
|
+
...(option.allOf ?? []),
|
|
40
|
+
...(option.prefixItems ?? []),
|
|
41
|
+
];
|
|
42
|
+
return children.some(hasRestrictedHints);
|
|
43
|
+
}
|
|
44
|
+
function isScalar(option) {
|
|
45
|
+
if (option.truncated || option.allOf || option.prefixItems)
|
|
46
|
+
return false;
|
|
47
|
+
return (["string", "number", "boolean"].includes(option.type) ||
|
|
48
|
+
(option.type === "union" &&
|
|
49
|
+
!!option.oneOf?.length &&
|
|
50
|
+
option.oneOf.every(isScalar)));
|
|
51
|
+
}
|
|
52
|
+
function hasValueEditor(option) {
|
|
53
|
+
if (hasRestrictedHints(option))
|
|
54
|
+
return false;
|
|
55
|
+
if (isScalar(option))
|
|
56
|
+
return true;
|
|
57
|
+
if (option.type === "array") {
|
|
58
|
+
// Content collections can carry demonstration rows even when enum-valued.
|
|
59
|
+
return (["appearance", "behavior", "layout", "features"].includes(option.ui?.group ?? "") &&
|
|
60
|
+
!!option.items?.enum?.length &&
|
|
61
|
+
isScalar(option.items));
|
|
62
|
+
}
|
|
63
|
+
if (option.type === "record") {
|
|
64
|
+
return (!!option.keys?.enum?.length && !!option.values && isScalar(option.values));
|
|
65
|
+
}
|
|
66
|
+
// Rich text and palettes can still use the scalar widget their schema declares.
|
|
67
|
+
return (option.type === "union" &&
|
|
68
|
+
!!option.ui?.widget &&
|
|
69
|
+
!!option.oneOf?.some(isScalar));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Dotted paths a standalone preview can edit without replacing data or opaque
|
|
73
|
+
* values. Objects are descended into, never offered as JSON. Only enum arrays
|
|
74
|
+
* in presentation/behavior groups and closed-key scalar records are editable
|
|
75
|
+
* collections; rows, slots and other structural collections remain fixed.
|
|
76
|
+
* Scalar unions have typed controls; a rich union with an explicit scalar
|
|
77
|
+
* widget (e.g. translated text or chart color) offers that scalar only.
|
|
78
|
+
*
|
|
79
|
+
* Fixed factory options exclude their entire top-level subtree. The returned
|
|
80
|
+
* paths reference `config`; consumers must not keep another copy of the schema.
|
|
81
|
+
*/
|
|
82
|
+
function BlockPresentationPaths(descriptor) {
|
|
83
|
+
const paths = [];
|
|
84
|
+
const walk = (config, prefix) => {
|
|
85
|
+
for (const [key, option] of Object.entries(config)) {
|
|
86
|
+
// Dots and prototype keys cannot be represented safely by path editors.
|
|
87
|
+
if (key.includes(".") ||
|
|
88
|
+
["__proto__", "constructor", "prototype"].includes(key))
|
|
89
|
+
continue;
|
|
90
|
+
if (!prefix && Object.hasOwn(descriptor.fixedOptions ?? {}, key))
|
|
91
|
+
continue;
|
|
92
|
+
if (!isPresentation(option))
|
|
93
|
+
continue;
|
|
94
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
95
|
+
if (option.allOf || option.prefixItems)
|
|
96
|
+
continue;
|
|
97
|
+
if (option.type === "object" && option.properties) {
|
|
98
|
+
walk(option.properties, path);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (hasValueEditor(option))
|
|
102
|
+
paths.push(path);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
walk(descriptor.config, "");
|
|
106
|
+
return paths;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=presentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../../src/base/block-registry/presentation.ts"],"names":[],"mappings":"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"}
|
package/dist/base/placeholder.js
CHANGED
|
@@ -15,11 +15,11 @@ exports.PlaceholderSchema = zod_1.z.object({
|
|
|
15
15
|
height: (0, block_registry_1.ui)(zod_1.z
|
|
16
16
|
.string()
|
|
17
17
|
.optional()
|
|
18
|
-
.describe("How tall the box is, such as 200px; left empty, it fills its place."), { label: "Height", group: "appearance" }),
|
|
18
|
+
.describe("How tall the box is, such as 200px; left empty, it fills its place."), { label: "Height", group: "appearance", advanced: true }),
|
|
19
19
|
width: (0, block_registry_1.ui)(zod_1.z
|
|
20
20
|
.string()
|
|
21
21
|
.optional()
|
|
22
|
-
.describe("How wide the box is, such as 300px; left empty, it fills its column."), { label: "Width", group: "appearance" }),
|
|
22
|
+
.describe("How wide the box is, such as 300px; left empty, it fills its column."), { label: "Width", group: "appearance", advanced: true }),
|
|
23
23
|
});
|
|
24
24
|
/**
|
|
25
25
|
* Placeholder - Development Placeholder Component
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../src/base/placeholder.ts"],"names":[],"mappings":";;;AAiEA,kCASC;AA1ED,4CAAgD;AAChD,6BAAwB;AACxB,qDAA+E;AAE/E,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAwBrD,yCAAyC;AAC5B,QAAA,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,IAAA,mBAAE,EAAC,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE;QACtE,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,SAAS;KACjB,CAAC;IACF,MAAM,EAAE,IAAA,mBAAE,EACR,OAAC;SACE,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,qEAAqE,CACtE,EACH,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../src/base/placeholder.ts"],"names":[],"mappings":";;;AAiEA,kCASC;AA1ED,4CAAgD;AAChD,6BAAwB;AACxB,qDAA+E;AAE/E,MAAM,0BAA0B,GAAG,iBAAiB,CAAC;AAwBrD,yCAAyC;AAC5B,QAAA,iBAAiB,GAAG,OAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,IAAA,mBAAE,EAAC,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE;QACtE,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,SAAS;KACjB,CAAC;IACF,MAAM,EAAE,IAAA,mBAAE,EACR,OAAC;SACE,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,qEAAqE,CACtE,EACH,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CACzD;IACD,KAAK,EAAE,IAAA,mBAAE,EACP,OAAC;SACE,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,sEAAsE,CACvE,EACH,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,CACxD;CACF,CAA+C,CAAC;AAEjD;;;;;;;;;;GAUG;AACH,SAAgB,WAAW,CACzB,OAA4B;IAE5B,OAAO,IAAI,4BAAgB,CAAqB,0BAA0B,CAAC;SACxE,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC;SACvB,IAAI,CAAC;QACJ,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,gBAAgB;KACvB,CAAC,CAAC;AACP,CAAC;AAED,IAAA,kCAAiB,EAAC;IAChB,IAAI,EAAE,aAAa;IACnB,aAAa,EAAE,0BAA0B;IACzC,MAAM,EAAE,yBAAiB;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,kDAAkD;QAC/D,KAAK,EAAE,QAAQ;KAChB;CACF,CAAC,CAAC"}
|
|
@@ -3,14 +3,14 @@ import { TenantMember, TenantMemberModel } from "../db";
|
|
|
3
3
|
import { DefaultDataTypes } from "../base/data-types/default-types";
|
|
4
4
|
declare const memberSettingDataAPI_base: import("@antelopejs/interface-core/decorators").Class<import("@antelopejs/interface-data-api").ExtractDefCallbacks<{
|
|
5
5
|
new: DataControllerCallback;
|
|
6
|
+
edit: DataControllerCallback;
|
|
7
|
+
delete: DataControllerCallback;
|
|
6
8
|
get: DataControllerCallback;
|
|
7
9
|
list: DataControllerCallback;
|
|
8
10
|
select: import("@antelopejs/interface-data-api").DataControllerCallbackWithOptions<any>;
|
|
9
11
|
count: DataControllerCallback;
|
|
10
12
|
countBatch: import("@antelopejs/interface-data-api").DataControllerCallbackWithOptions<any>;
|
|
11
13
|
summary: import("@antelopejs/interface-data-api").DataControllerCallbackWithOptions<any>;
|
|
12
|
-
edit: DataControllerCallback;
|
|
13
|
-
delete: DataControllerCallback;
|
|
14
14
|
archive: DataControllerCallback;
|
|
15
15
|
restore: DataControllerCallback;
|
|
16
16
|
}> & {
|
|
@@ -31,14 +31,21 @@ const SYSTEM_MANAGED_FIELD = {
|
|
|
31
31
|
view: types_1.ReadonlyBehaviorType.disabled,
|
|
32
32
|
new: types_1.ReadonlyBehaviorType.hidden,
|
|
33
33
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
34
|
+
function admittedMemberRoute(route) {
|
|
35
|
+
return {
|
|
36
|
+
...route,
|
|
37
|
+
async func(...args) {
|
|
38
|
+
const [ctx] = args;
|
|
39
|
+
return (0, tenant_lifecycle_1.runTenantLifecycleOperation)((0, request_tenant_1.getRequestTenantId)(ctx), () => route.func.apply(this, args));
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
class memberSettingDataAPI extends (0, interface_data_api_1.DataController)(db_1.TenantMember, {
|
|
44
|
+
...table_view_1.TableViewRoutes.All,
|
|
45
|
+
new: admittedMemberRoute(table_view_1.TableViewRoutes.New),
|
|
46
|
+
edit: admittedMemberRoute(table_view_1.TableViewRoutes.Edit),
|
|
47
|
+
delete: admittedMemberRoute(table_view_1.TableViewRoutes.Delete),
|
|
48
|
+
}, (0, interface_api_1.Controller)("/api/tables/members")) {
|
|
42
49
|
}
|
|
43
50
|
exports.memberSettingDataAPI = memberSettingDataAPI;
|
|
44
51
|
__decorate([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../src/data-controllers/members.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAAuD;AACvD,uEAGwC;AACxC,sEAOiD;AACjD,8BAAwD;AACxD,gEAA2D;AAC3D,mCAAkC;AAClC,oEAAoE;AACpE,mDAAgD;AAChD,mDAM4B;AAC5B,yCAAqD;AACrD,sDAAuD;AACvD,0DAAkE;AAClE,mCAA6C;AAE7C,MAAM,gBAAgB,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAW,CAAC;AAElE,oEAAoE;AACpE,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEpC,MAAM,oBAAoB,GAAG;IAC3B,IAAI,EAAE,4BAAoB,CAAC,MAAM;IACjC,IAAI,EAAE,4BAAoB,CAAC,QAAQ;IACnC,GAAG,EAAE,4BAAoB,CAAC,MAAM;CACjC,CAAC;AAEF,
|
|
1
|
+
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../src/data-controllers/members.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,10 @@ export declare class TenantLifecycleModel extends TenantLifecycleModel_base {
|
|
|
29
29
|
private transition;
|
|
30
30
|
/** Only a confirmed admission permits effects; unknown outcomes fail closed. */
|
|
31
31
|
admit(tenantId: string, attemptId: string): Promise<void>;
|
|
32
|
+
/** One CAS only: a delayed caller must not acquire against a newer revision. */
|
|
33
|
+
pause(tenantId: string, barrierId: string, expectedRevision: string): Promise<boolean>;
|
|
34
|
+
/** Also revokes an in-flight acquisition when no barrier has landed yet. */
|
|
35
|
+
resume(tenantId: string, barrierId: string): Promise<boolean>;
|
|
32
36
|
/** Called only by the invocation that has finished every awaited producer effect. */
|
|
33
37
|
finish(tenantId: string, attemptId: string): Promise<void>;
|
|
34
38
|
/** Closes permanently before testing quiescence; active or uncertain work blocks deletion. */
|
|
@@ -54,12 +54,35 @@ class TenantLifecycleModel extends (0, interface_database_decorators_1.BasicData
|
|
|
54
54
|
const state = await this.state(tenantId);
|
|
55
55
|
if (state.closed)
|
|
56
56
|
throw new Error("Tenant lifecycle admission is closed");
|
|
57
|
+
if (state.barrierId)
|
|
58
|
+
throw new Error("Tenant lifecycle admission is paused");
|
|
57
59
|
if (await this.transition(state, {
|
|
58
60
|
activeAttemptIds: [...state.activeAttemptIds, attemptId],
|
|
59
61
|
}))
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
/** One CAS only: a delayed caller must not acquire against a newer revision. */
|
|
66
|
+
async pause(tenantId, barrierId, expectedRevision) {
|
|
67
|
+
if (!barrierId)
|
|
68
|
+
throw new Error("Tenant lifecycle barrier requires an identity");
|
|
69
|
+
const state = await this.state(tenantId);
|
|
70
|
+
if (state.closed || state.barrierId || state.revision !== expectedRevision)
|
|
71
|
+
return false;
|
|
72
|
+
return this.transition(state, { barrierId });
|
|
73
|
+
}
|
|
74
|
+
/** Also revokes an in-flight acquisition when no barrier has landed yet. */
|
|
75
|
+
async resume(tenantId, barrierId) {
|
|
76
|
+
if (!barrierId)
|
|
77
|
+
throw new Error("Tenant lifecycle barrier requires an identity");
|
|
78
|
+
while (true) {
|
|
79
|
+
const state = await this.state(tenantId);
|
|
80
|
+
if (state.closed || (state.barrierId && state.barrierId !== barrierId))
|
|
81
|
+
return false;
|
|
82
|
+
if (await this.transition(state, { barrierId: null }))
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
63
86
|
/** Called only by the invocation that has finished every awaited producer effect. */
|
|
64
87
|
async finish(tenantId, attemptId) {
|
|
65
88
|
while (true) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenantLifecycle.model.js","sourceRoot":"","sources":["../../../src/db/internal/tenantLifecycle.model.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tenantLifecycle.model.js","sourceRoot":"","sources":["../../../src/db/internal/tenantLifecycle.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,10 @@ __decorate([
|
|
|
38
38
|
(0, interface_database_decorators_1.Field)(["string"]),
|
|
39
39
|
__metadata("design:type", Array)
|
|
40
40
|
], TenantLifecycle.prototype, "activeAttemptIds", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, interface_database_decorators_1.Field)("string"),
|
|
43
|
+
__metadata("design:type", Object)
|
|
44
|
+
], TenantLifecycle.prototype, "barrierId", void 0);
|
|
41
45
|
exports.TenantLifecycle = TenantLifecycle = __decorate([
|
|
42
46
|
(0, interface_database_decorators_1.RegisterTable)(exports.tenantLifecycleTableName, constants_1.TENANT_SCHEMA_NAME)
|
|
43
47
|
], TenantLifecycle);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenantLifecycle.table.js","sourceRoot":"","sources":["../../../src/db/internal/tenantLifecycle.table.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6FAImD;AACnD,+CAAqD;AAErD,gBAAgB;AACH,QAAA,wBAAwB,GAAG,kBAAkB,CAAC;AAE3D;;;;GAIG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,qCAAK;
|
|
1
|
+
{"version":3,"file":"tenantLifecycle.table.js","sourceRoot":"","sources":["../../../src/db/internal/tenantLifecycle.table.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6FAImD;AACnD,+CAAqD;AAErD,gBAAgB;AACH,QAAA,wBAAwB,GAAG,kBAAkB,CAAC;AAE3D;;;;GAIG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,qCAAK;CAMzC,CAAA;AANY,0CAAe;AACD;IAAxB,IAAA,qCAAK,EAAC,QAAQ,CAAC;;4CAAqB;AACZ;IAAxB,IAAA,qCAAK,EAAC,QAAQ,CAAC;;iDAA0B;AAChB;IAAzB,IAAA,qCAAK,EAAC,SAAS,CAAC;;+CAAyB;AACf;IAA1B,IAAA,qCAAK,EAAC,CAAC,QAAQ,CAAC,CAAC;;yDAAoC;AAC7B;IAAxB,IAAA,qCAAK,EAAC,QAAQ,CAAC;;kDAAmC;0BALxC,eAAe;IAD3B,IAAA,6CAAa,EAAC,gCAAwB,EAAE,8BAAkB,CAAC;GAC/C,eAAe,CAM3B"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export declare enum Hook {
|
|
|
41
41
|
INVITE_CREATED = "invite:created",
|
|
42
42
|
INVITE_DELETED = "invite:deleted",
|
|
43
43
|
MEMBER_BEING_ADDED = "member:being-added",
|
|
44
|
+
/** Policy veto under lifecycle admission, before a membership write. */
|
|
45
|
+
MEMBER_BEING_CHANGED = "member:being-changed",
|
|
44
46
|
MEMBER_ADDED = "member:added",
|
|
45
47
|
MEMBER_REMOVED = "member:removed",
|
|
46
48
|
USER_REGISTERED = "user:registered",
|
|
@@ -107,6 +109,11 @@ export interface InviteDeletedHookPayload {
|
|
|
107
109
|
/** Payloads the invitation carried, for handlers that must undo their work. */
|
|
108
110
|
extensions?: InviteExtensionPayloads | null;
|
|
109
111
|
}
|
|
112
|
+
/** Seat classification belongs to the consumer, including support exemptions. */
|
|
113
|
+
export interface MemberChangeHookPayload extends MemberHookPayload {
|
|
114
|
+
/** Null for a new membership; deliveryId does not exempt it from policy. */
|
|
115
|
+
previousIsTenantOwner: boolean | null;
|
|
116
|
+
}
|
|
110
117
|
export interface MemberHookPayload {
|
|
111
118
|
tenantId: string;
|
|
112
119
|
userId: string;
|
|
@@ -171,6 +178,10 @@ export interface HookSignatures {
|
|
|
171
178
|
args: [payload: MemberHookPayload];
|
|
172
179
|
result: undefined;
|
|
173
180
|
};
|
|
181
|
+
[Hook.MEMBER_BEING_CHANGED]: {
|
|
182
|
+
args: [payload: MemberChangeHookPayload];
|
|
183
|
+
result: undefined;
|
|
184
|
+
};
|
|
174
185
|
[Hook.MEMBER_ADDED]: {
|
|
175
186
|
args: [payload: MemberHookPayload];
|
|
176
187
|
result: undefined;
|
package/dist/hooks.js
CHANGED
|
@@ -67,6 +67,8 @@ var Hook;
|
|
|
67
67
|
Hook["INVITE_CREATED"] = "invite:created";
|
|
68
68
|
Hook["INVITE_DELETED"] = "invite:deleted";
|
|
69
69
|
Hook["MEMBER_BEING_ADDED"] = "member:being-added";
|
|
70
|
+
/** Policy veto under lifecycle admission, before a membership write. */
|
|
71
|
+
Hook["MEMBER_BEING_CHANGED"] = "member:being-changed";
|
|
70
72
|
Hook["MEMBER_ADDED"] = "member:added";
|
|
71
73
|
Hook["MEMBER_REMOVED"] = "member:removed";
|
|
72
74
|
Hook["USER_REGISTERED"] = "user:registered";
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,13 @@ async function beginMembership(resolution) {
|
|
|
18
18
|
await model.advanceMembership(resolution, "applied");
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
+
await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_CHANGED, {
|
|
22
|
+
tenantId,
|
|
23
|
+
userId,
|
|
24
|
+
isTenantOwner: invite.asTenantOwner,
|
|
25
|
+
previousIsTenantOwner: null,
|
|
26
|
+
deliveryId: resolution._id,
|
|
27
|
+
});
|
|
21
28
|
await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_ADDED, {
|
|
22
29
|
tenantId,
|
|
23
30
|
userId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invite-membership.js","sourceRoot":"","sources":["../../src/internal/invite-membership.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"invite-membership.js","sourceRoot":"","sources":["../../src/internal/invite-membership.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,6 +50,15 @@ async function applyAdmittedTenantOwnership(userModel, userId, tenantId, patch)
|
|
|
50
50
|
const memberModel = (0, interface_database_decorators_1.GetModel)(tenantMembers_model_1.TenantMemberModel, tenantId);
|
|
51
51
|
const existing = await memberModel.getByUser(userId);
|
|
52
52
|
const isNewMember = !existing;
|
|
53
|
+
// Invite delivery checks policy before its durable applying phase, not here.
|
|
54
|
+
if (!patch.deliveryId) {
|
|
55
|
+
await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_CHANGED, {
|
|
56
|
+
tenantId,
|
|
57
|
+
userId,
|
|
58
|
+
isTenantOwner: patch.isTenantOwner,
|
|
59
|
+
previousIsTenantOwner: existing ? existing.isTenantOwner === true : null,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
53
62
|
if (isNewMember && !patch.deliveryId) {
|
|
54
63
|
const payload = {
|
|
55
64
|
tenantId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../../src/internal/tenant-ownership.ts"],"names":[],"mappings":";;AAiDA,
|
|
1
|
+
{"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../../src/internal/tenant-ownership.ts"],"names":[],"mappings":"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"}
|
package/dist/tenant-access.d.ts
CHANGED
|
@@ -50,6 +50,21 @@ export declare function RegisterTenantAccessGate(info: TenantAccessGateInfo): vo
|
|
|
50
50
|
* undefined for unauthenticated requests.
|
|
51
51
|
*/
|
|
52
52
|
export declare const CheckTenantAccess: (userId: string | undefined, tenantId: string) => Promise<TenantAccessResult>;
|
|
53
|
+
/** One denying gate, identified independently of its user-facing error code. */
|
|
54
|
+
export interface TenantAccessDenial {
|
|
55
|
+
gateId: string;
|
|
56
|
+
code: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Server-side evaluation of every registered gate, in gate order. Returns all
|
|
60
|
+
* denials (empty when allowed); any exception rejects the whole evaluation.
|
|
61
|
+
* Unlike CheckTenantAccess, an early denial does not hide later blockers.
|
|
62
|
+
* This is an observation, not an authorization receipt or an atomic snapshot
|
|
63
|
+
* of external state. Callers must preserve other holds and revalidate their
|
|
64
|
+
* operation's authorization before effects. Never infer ownership from code.
|
|
65
|
+
* Does not change the first-denial response of user-facing access checks.
|
|
66
|
+
*/
|
|
67
|
+
export declare const EvaluateTenantAccess: (userId: string | undefined, tenantId: string) => Promise<TenantAccessDenial[]>;
|
|
53
68
|
/**
|
|
54
69
|
* Assert that the tenant is accessible; throws a 403 whose body is the
|
|
55
70
|
* denying gate's `code` (a machine-readable i18n key) otherwise.
|
package/dist/tenant-access.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CheckTenantAccess = exports.internal = void 0;
|
|
3
|
+
exports.EvaluateTenantAccess = exports.CheckTenantAccess = exports.internal = void 0;
|
|
4
4
|
exports.RegisterTenantAccessGate = RegisterTenantAccessGate;
|
|
5
5
|
exports.AssertTenantAccess = AssertTenantAccess;
|
|
6
6
|
const interface_api_1 = require("@antelopejs/interface-api");
|
|
@@ -48,6 +48,16 @@ function RegisterTenantAccessGate(info) {
|
|
|
48
48
|
* undefined for unauthenticated requests.
|
|
49
49
|
*/
|
|
50
50
|
exports.CheckTenantAccess = (0, interface_core_1.InterfaceFunction)();
|
|
51
|
+
/**
|
|
52
|
+
* Server-side evaluation of every registered gate, in gate order. Returns all
|
|
53
|
+
* denials (empty when allowed); any exception rejects the whole evaluation.
|
|
54
|
+
* Unlike CheckTenantAccess, an early denial does not hide later blockers.
|
|
55
|
+
* This is an observation, not an authorization receipt or an atomic snapshot
|
|
56
|
+
* of external state. Callers must preserve other holds and revalidate their
|
|
57
|
+
* operation's authorization before effects. Never infer ownership from code.
|
|
58
|
+
* Does not change the first-denial response of user-facing access checks.
|
|
59
|
+
*/
|
|
60
|
+
exports.EvaluateTenantAccess = (0, interface_core_1.InterfaceFunction)();
|
|
51
61
|
/**
|
|
52
62
|
* Assert that the tenant is accessible; throws a 403 whose body is the
|
|
53
63
|
* denying gate's `code` (a machine-readable i18n key) otherwise.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-access.js","sourceRoot":"","sources":["../src/tenant-access.ts"],"names":[],"mappings":";;;AA0DA,4DAEC;
|
|
1
|
+
{"version":3,"file":"tenant-access.js","sourceRoot":"","sources":["../src/tenant-access.ts"],"names":[],"mappings":";;;AA0DA,4DAEC;AA0CD,gDAQC;AA9GD,6DAAuD;AACvD,+DAGoC;AAEpC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAiBlC;;GAEG;AACH,IAAiB,QAAQ,CAIxB;AAJD,WAAiB,QAAQ;IACV,iCAAwB,GAAG,IAAI,iCAAgB,EAEzD,CAAC;AACN,CAAC,EAJgB,QAAQ,wBAAR,QAAQ,QAIxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,wBAAwB,CAAC,IAA0B;IACjE,QAAQ,CAAC,wBAAwB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACU,QAAA,iBAAiB,GAC5B,IAAA,kCAAiB,GAKd,CAAC;AAQN;;;;;;;;GAQG;AACU,QAAA,oBAAoB,GAC/B,IAAA,kCAAiB,GAKd,CAAC;AAEN;;;GAGG;AACI,KAAK,UAAU,kBAAkB,CACtC,MAA0B,EAC1B,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAiB,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,0BAAU,CAAC,qBAAqB,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -13,3 +13,30 @@ export declare function runTenantLifecycleOperation<T>(tenantId: string, work: (
|
|
|
13
13
|
* rejection requires preserving data, never timeout-based takeover or reopening.
|
|
14
14
|
*/
|
|
15
15
|
export declare function closeTenantLifecycleAdmission(tenantId: string): Promise<void>;
|
|
16
|
+
/** A non-destructive snapshot; no attempt expires or is retired by observation. */
|
|
17
|
+
export interface TenantLifecycleObservation {
|
|
18
|
+
revision: string;
|
|
19
|
+
barrierId: string | null;
|
|
20
|
+
activeAttemptIds: string[];
|
|
21
|
+
closed: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Observe outside a producer callback: an initiator must not drain itself. */
|
|
24
|
+
export declare function observeTenantLifecycle(tenantId: string): Promise<TenantLifecycleObservation>;
|
|
25
|
+
/**
|
|
26
|
+
* Publish a temporary barrier on the same CAS revision as producer admission.
|
|
27
|
+
* Use a unique identity per phase, never reuse it. Observe the revision BEFORE
|
|
28
|
+
* checking the durable business intent, then attempt this single CAS. After
|
|
29
|
+
* acquisition recheck that intent; release if abandoned. False requires a new
|
|
30
|
+
* observation and intent check, not a blind retry. Unknown outcomes throw.
|
|
31
|
+
* Existing attempts keep running; only an empty observation while this barrier
|
|
32
|
+
* remains owned permits inventory validation. No Stripe calls under a barrier.
|
|
33
|
+
*/
|
|
34
|
+
export declare function pauseTenantLifecycleAdmission(tenantId: string, barrierId: string, expectedRevision: string): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Release this owner's barrier, or invalidate the revision when none is held.
|
|
37
|
+
* The latter revokes a delayed acquisition after its business intent is aborted.
|
|
38
|
+
* Never reopens permanent deletion closure or another owner's barrier (false).
|
|
39
|
+
* Retains every active/uncertain attempt; timeout is not evidence of completion.
|
|
40
|
+
* Publish pending policy before release so newly admitted producers read it.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resumeTenantLifecycleAdmission(tenantId: string, barrierId: string): Promise<boolean>;
|
package/dist/tenant-lifecycle.js
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.runTenantLifecycleOperation = runTenantLifecycleOperation;
|
|
4
4
|
exports.closeTenantLifecycleAdmission = closeTenantLifecycleAdmission;
|
|
5
|
+
exports.observeTenantLifecycle = observeTenantLifecycle;
|
|
6
|
+
exports.pauseTenantLifecycleAdmission = pauseTenantLifecycleAdmission;
|
|
7
|
+
exports.resumeTenantLifecycleAdmission = resumeTenantLifecycleAdmission;
|
|
5
8
|
const node_crypto_1 = require("node:crypto");
|
|
6
9
|
const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
|
|
7
10
|
const tenantLifecycle_model_1 = require("./db/internal/tenantLifecycle.model");
|
|
@@ -55,4 +58,36 @@ async function runTenantLifecycleOperation(tenantId, work) {
|
|
|
55
58
|
async function closeTenantLifecycleAdmission(tenantId) {
|
|
56
59
|
await (0, interface_database_decorators_1.GetModel)(tenantLifecycle_model_1.TenantLifecycleModel, tenantId).close(tenantId);
|
|
57
60
|
}
|
|
61
|
+
/** Observe outside a producer callback: an initiator must not drain itself. */
|
|
62
|
+
async function observeTenantLifecycle(tenantId) {
|
|
63
|
+
const state = await (0, interface_database_decorators_1.GetModel)(tenantLifecycle_model_1.TenantLifecycleModel, tenantId).state(tenantId);
|
|
64
|
+
return {
|
|
65
|
+
revision: state.revision,
|
|
66
|
+
barrierId: state.barrierId ?? null,
|
|
67
|
+
activeAttemptIds: [...state.activeAttemptIds],
|
|
68
|
+
closed: state.closed,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Publish a temporary barrier on the same CAS revision as producer admission.
|
|
73
|
+
* Use a unique identity per phase, never reuse it. Observe the revision BEFORE
|
|
74
|
+
* checking the durable business intent, then attempt this single CAS. After
|
|
75
|
+
* acquisition recheck that intent; release if abandoned. False requires a new
|
|
76
|
+
* observation and intent check, not a blind retry. Unknown outcomes throw.
|
|
77
|
+
* Existing attempts keep running; only an empty observation while this barrier
|
|
78
|
+
* remains owned permits inventory validation. No Stripe calls under a barrier.
|
|
79
|
+
*/
|
|
80
|
+
async function pauseTenantLifecycleAdmission(tenantId, barrierId, expectedRevision) {
|
|
81
|
+
return (0, interface_database_decorators_1.GetModel)(tenantLifecycle_model_1.TenantLifecycleModel, tenantId).pause(tenantId, barrierId, expectedRevision);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Release this owner's barrier, or invalidate the revision when none is held.
|
|
85
|
+
* The latter revokes a delayed acquisition after its business intent is aborted.
|
|
86
|
+
* Never reopens permanent deletion closure or another owner's barrier (false).
|
|
87
|
+
* Retains every active/uncertain attempt; timeout is not evidence of completion.
|
|
88
|
+
* Publish pending policy before release so newly admitted producers read it.
|
|
89
|
+
*/
|
|
90
|
+
async function resumeTenantLifecycleAdmission(tenantId, barrierId) {
|
|
91
|
+
return (0, interface_database_decorators_1.GetModel)(tenantLifecycle_model_1.TenantLifecycleModel, tenantId).resume(tenantId, barrierId);
|
|
92
|
+
}
|
|
58
93
|
//# sourceMappingURL=tenant-lifecycle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-lifecycle.js","sourceRoot":"","sources":["../src/tenant-lifecycle.ts"],"names":[],"mappings":";;AAkCA,kEAoBC;AAMD,sEAIC;
|
|
1
|
+
{"version":3,"file":"tenant-lifecycle.js","sourceRoot":"","sources":["../src/tenant-lifecycle.ts"],"names":[],"mappings":";;AAkCA,kEAoBC;AAMD,sEAIC;AAWD,wDAUC;AAWD,sEAUC;AASD,wEAKC;AAxHD,6CAAyC;AACzC,6FAAqE;AACrE,+EAA2E;AAE3E,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAOlC;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,KAAc;IACzC,MAAM,SAAS,GAAI,KAAuC,EAAE,SAAS,CAAC;IACtE,IAAI,OAAO,SAAS,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,OAAO,MAAM,IAAI,qBAAqB,IAAI,MAAM,GAAG,qBAAqB,CAAC;AAC3E,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,2BAA2B,CAC/C,QAAgB,EAChB,IAAsB;IAEtB,MAAM,KAAK,GAAG,IAAA,wCAAQ,EAAC,4CAAoB,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAA,wBAAU,GAAE,CAAC;IAC/B,MAAM,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACvC,IAAI,MAAS,CAAC;IACd,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAI,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,wEAAwE;YACxE,mDAAmD;YACnD,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,6BAA6B,CACjD,QAAgB;IAEhB,MAAM,IAAA,wCAAQ,EAAC,4CAAoB,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACjE,CAAC;AAUD,+EAA+E;AACxE,KAAK,UAAU,sBAAsB,CAC1C,QAAgB;IAEhB,MAAM,KAAK,GAAG,MAAM,IAAA,wCAAQ,EAAC,4CAAoB,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7E,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;QAClC,gBAAgB,EAAE,CAAC,GAAG,KAAK,CAAC,gBAAgB,CAAC;QAC7C,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,6BAA6B,CACjD,QAAgB,EAChB,SAAiB,EACjB,gBAAwB;IAExB,OAAO,IAAA,wCAAQ,EAAC,4CAAoB,EAAE,QAAQ,CAAC,CAAC,KAAK,CACnD,QAAQ,EACR,SAAS,EACT,gBAAgB,CACjB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,8BAA8B,CAClD,QAAgB,EAChB,SAAiB;IAEjB,OAAO,IAAA,wCAAQ,EAAC,4CAAoB,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC9E,CAAC"}
|
package/dist/tenant-ownership.js
CHANGED
|
@@ -3,11 +3,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.applyTenantOwnership = applyTenantOwnership;
|
|
4
4
|
exports.syncPlatformOwnerOnTenantOwnerChange = syncPlatformOwnerOnTenantOwnerChange;
|
|
5
5
|
exports.clearPlatformOwnerOnMemberRemoval = clearPlatformOwnerOnMemberRemoval;
|
|
6
|
+
const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
|
|
7
|
+
const tenantMembers_model_1 = require("./db/models/tenantMembers.model");
|
|
8
|
+
const hooks_1 = require("./hooks");
|
|
6
9
|
const tenant_lifecycle_1 = require("./tenant-lifecycle");
|
|
7
10
|
const tenant_ownership_1 = require("./internal/tenant-ownership");
|
|
8
11
|
/** Admits membership writes before a tenant can begin destructive deletion. */
|
|
9
12
|
async function applyTenantOwnership(userModel, userId, tenantId, patch) {
|
|
10
|
-
await (0, tenant_lifecycle_1.runTenantLifecycleOperation)(tenantId, () =>
|
|
13
|
+
await (0, tenant_lifecycle_1.runTenantLifecycleOperation)(tenantId, async () => {
|
|
14
|
+
// Public callers supplying a delivery identity still need the policy veto.
|
|
15
|
+
// Internal resolution checks it before persisting its applying phase.
|
|
16
|
+
if (patch.deliveryId &&
|
|
17
|
+
!(await (0, interface_database_decorators_1.GetModel)(tenantMembers_model_1.TenantMemberModel, tenantId).getByUser(userId))) {
|
|
18
|
+
await (0, hooks_1.ExecuteHooks)(hooks_1.Hook.MEMBER_BEING_CHANGED, {
|
|
19
|
+
tenantId,
|
|
20
|
+
userId,
|
|
21
|
+
isTenantOwner: patch.isTenantOwner,
|
|
22
|
+
previousIsTenantOwner: null,
|
|
23
|
+
deliveryId: patch.deliveryId,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
await (0, tenant_ownership_1.applyAdmittedTenantOwnership)(userModel, userId, tenantId, patch);
|
|
27
|
+
});
|
|
11
28
|
}
|
|
12
29
|
async function syncPlatformOwnerOnTenantOwnerChange(userModel, userId, tenantId, nextIsTenantOwner) {
|
|
13
30
|
await (0, tenant_ownership_1.mirrorPlatformOwner)(userModel, userId, tenantId, nextIsTenantOwner);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../src/tenant-ownership.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"tenant-ownership.js","sourceRoot":"","sources":["../src/tenant-ownership.ts"],"names":[],"mappings":";;AAmBA,oDAuBC;AAED,oFAOC;AAED,8EAQC;AA5DD,6FAAqE;AACrE,yEAAoE;AACpE,mCAA6C;AAC7C,yDAAiE;AACjE,kEAGqC;AAUrC,+EAA+E;AACxE,KAAK,UAAU,oBAAoB,CACxC,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,KAA4B;IAE5B,MAAM,IAAA,8CAA2B,EAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QACrD,2EAA2E;QAC3E,sEAAsE;QACtE,IACE,KAAK,CAAC,UAAU;YAChB,CAAC,CAAC,MAAM,IAAA,wCAAQ,EAAC,uCAAiB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAChE,CAAC;YACD,MAAM,IAAA,oBAAY,EAAC,YAAI,CAAC,oBAAoB,EAAE;gBAC5C,QAAQ;gBACR,MAAM;gBACN,aAAa,EAAE,KAAK,CAAC,aAAa;gBAClC,qBAAqB,EAAE,IAAI;gBAC3B,UAAU,EAAE,KAAK,CAAC,UAAU;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,MAAM,IAAA,+CAA4B,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,oCAAoC,CACxD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,iBAA0B;IAE1B,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC5E,CAAC;AAEM,KAAK,UAAU,iCAAiC,CACrD,SAAoB,EACpB,MAAc,EACd,QAAgB,EAChB,2BAAoC;IAEpC,IAAI,CAAC,2BAA2B;QAAE,OAAO;IACzC,MAAM,IAAA,sCAAmB,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -9,6 +9,8 @@ description: "Pages are controller classes registered into a navigation tree of
|
|
|
9
9
|
|
|
10
10
|
A page is a controller class. `PageController(id, options, layout?)` builds a base class bound to a URL, `@RegisterPage()` records it, and the components declared as static fields on the class become the page's serialized layout. Categories group pages into the sidebar tree, and modules group a whole set of pages and categories under their own root.
|
|
11
11
|
|
|
12
|
+
Building your first screen? Follow [Pages & components](/docs/building/pages-and-components) first. This reference covers registration, identifiers, and lifecycle rules. The guide also shows [page-extension placement](/docs/building/pages-and-components#extending-another-modules-page) in the running playground.
|
|
13
|
+
|
|
12
14
|
Everything on this page lives in `@antelopejs/interface-dms/page`.
|
|
13
15
|
|
|
14
16
|
Registration happens at import time: the `@RegisterPage()` decorator runs when the file is loaded, so the order in which you import page files determines the order in which pages, categories and their permissions are registered.
|
package/docs/1.core/5.tenancy.md
CHANGED
|
@@ -9,6 +9,8 @@ description: "The DMS serves several tenants from one backend."
|
|
|
9
9
|
|
|
10
10
|
The DMS serves several tenants from one backend. Tenant-owned tables live in a per-tenant schema, and a model handle is bound to one tenant when you obtain it: `GetModel(TenantMemberModel, tenantId)` reads and writes that tenant's rows only. No query filters rows by tenant, and no table carries a `tenantId` column — the isolation is in the handle.
|
|
11
11
|
|
|
12
|
+
For a first implementation, follow [Multi-tenant data](/docs/auth-and-tenancy/multi-tenant): register the table in the tenant schema, protect the route, and inject a tenant-bound model. Use this reference for the schema constants and lifecycle contracts. **Resolving a tenant id is not an authorization check**; `getRequestTenantId` must run behind authentication.
|
|
13
|
+
|
|
12
14
|
The tenancy surface spans several subpaths:
|
|
13
15
|
|
|
14
16
|
| Subpath | Contains |
|
|
@@ -232,6 +234,7 @@ Two functions evaluate the gates:
|
|
|
232
234
|
| -------- | -------- |
|
|
233
235
|
| `CheckTenantAccess(userId, tenantId)` | Resolves to the first denial, or `{ allowed: true }`. |
|
|
234
236
|
| `AssertTenantAccess(userId, tenantId)` | Calls `CheckTenantAccess` and throws a `403` whose body is the denying gate's `code`. |
|
|
237
|
+
| `EvaluateTenantAccess(userId, tenantId)` | Server-side only. Resolves to every denial as `{ gateId, code }[]`, in gate order, `[]` when none; a gate that throws rejects the whole evaluation. |
|
|
235
238
|
|
|
236
239
|
```typescript
|
|
237
240
|
import {
|
|
@@ -249,6 +252,8 @@ await AssertTenantAccess(user._id, tenantId); // or let it throw
|
|
|
249
252
|
|
|
250
253
|
`AuthTenantOwner` and `AuthTenantMember` call `AssertTenantAccess` unless the route opts out with `bypassTenantAccessGate` ([Permissions](/docs/interfaces/core/permissions)).
|
|
251
254
|
|
|
255
|
+
`EvaluateTenantAccess` exists for modules that must know whether a denial other than their own is in place, for example before lifting a hold: identify gates by `gateId`, never by `code`, which two gates may share. Its result is an observation, not an authorization receipt or an atomic snapshot of external state; revalidate before acting on it.
|
|
256
|
+
|
|
252
257
|
Use a gate to deny a tenant outright; use a permissions resolver to shape what its users may do.
|
|
253
258
|
|
|
254
259
|
## Memberships and Ownership
|
|
@@ -274,7 +279,7 @@ await applyTenantOwnership(GetModel(UserModel), userId, tenantId, {
|
|
|
274
279
|
| `isTenantOwner` | `boolean` | Ownership flag after the write. |
|
|
275
280
|
| `invitedBy` | `string \| null` | Recorded on insert. Ignored when the membership row already exists. |
|
|
276
281
|
|
|
277
|
-
When the user is not yet a member,
|
|
282
|
+
`applyTenantOwnership` fires `Hook.MEMBER_BEING_CHANGED` before any write, so a module can veto it. When the user is not yet a member, it also fires `Hook.MEMBER_BEING_ADDED` before the write and `Hook.MEMBER_ADDED` after it. For an existing member it updates `roleIds` and `isTenantOwner` and fires neither of those two ([Hooks](/docs/interfaces/core/hooks)).
|
|
278
283
|
|
|
279
284
|
Two helpers keep the legacy platform-owner flag on the user row aligned with tenant ownership:
|
|
280
285
|
|
|
@@ -314,6 +319,18 @@ Membership and invite producers coordinate with tenant deletion through `@antelo
|
|
|
314
319
|
|
|
315
320
|
A successful callback releases its admission. A deliberate HTTP 4xx refusal also attempts release and rethrows the original refusal; other failures retain admission because their effects may be indeterminate. Retrying is a new invocation and never retires the failed one's identity. There is no automatic expiry or reconciliation API.
|
|
316
321
|
|
|
322
|
+
### Pausing Admission
|
|
323
|
+
|
|
324
|
+
A module that must validate a tenant's inventory with no membership writer in flight, such as a plan downgrade, pauses admission instead of closing it:
|
|
325
|
+
|
|
326
|
+
| Function | Behavior |
|
|
327
|
+
| -------- | -------- |
|
|
328
|
+
| `observeTenantLifecycle(tenantId)` | Resolves to `{ revision, barrierId, activeAttemptIds, closed }`. Never retires an attempt. |
|
|
329
|
+
| `pauseTenantLifecycleAdmission(tenantId, barrierId, expectedRevision)` | Publishes the barrier with one compare-and-set on `expectedRevision`. Resolves `false` when the revision moved, a barrier is held or admission is closed. |
|
|
330
|
+
| `resumeTenantLifecycleAdmission(tenantId, barrierId)` | Releases this barrier; with no barrier held, it invalidates the revision so a delayed `pause` fails. Resolves `false` for another owner's barrier or closed admission. |
|
|
331
|
+
|
|
332
|
+
While a barrier is held, `runTenantLifecycleOperation` rejects new work without running it; admitted work keeps running. Observe the revision before checking your own business intent, pause with that revision, recheck the intent, then wait for an observation with no active attempt before validating. A `false` from `pause` needs a new observation, not a blind retry. Use a unique `barrierId` per phase, and do not observe or pause from inside a `runTenantLifecycleOperation` callback: the caller would wait for itself.
|
|
333
|
+
|
|
317
334
|
### `closeTenantLifecycleAdmission`
|
|
318
335
|
|
|
319
336
|
`closeTenantLifecycleAdmission(tenantId: string): Promise<void>` permanently closes admission, then checks that no admitted operation remains. It rejects if work is active or indeterminate, or if the database cannot confirm the transition. Rejection can leave admission closed: it never authorizes deletion or reopening.
|
package/docs/1.core/7.hooks.md
CHANGED
|
@@ -76,6 +76,7 @@ UnregisterHook(Hook.MEMBER_ADDED, onMemberAdded);
|
|
|
76
76
|
| `Hook.INVITE_CREATED` | `"invite:created"` | `InviteCreatedHookPayload` | `undefined` |
|
|
77
77
|
| `Hook.INVITE_DELETED` | `"invite:deleted"` | `InviteDeletedHookPayload` | `undefined` |
|
|
78
78
|
| `Hook.MEMBER_BEING_ADDED` | `"member:being-added"` | `MemberHookPayload` | `undefined` |
|
|
79
|
+
| `Hook.MEMBER_BEING_CHANGED` | `"member:being-changed"` | `MemberChangeHookPayload` | `undefined` — fires under tenant lifecycle admission before a membership is created or its ownership changes; throwing vetoes the write |
|
|
79
80
|
| `Hook.MEMBER_ADDED` | `"member:added"` | `MemberHookPayload` | `undefined` |
|
|
80
81
|
| `Hook.MEMBER_REMOVED` | `"member:removed"` | `MemberRemovedHookPayload` | `undefined` |
|
|
81
82
|
| `Hook.USER_REGISTERED` | `"user:registered"` | `UserRegisteredHookPayload` | `undefined` |
|
|
@@ -140,6 +141,8 @@ interface UserDeletedHookPayload {
|
|
|
140
141
|
|
|
141
142
|
The shapes are not uniform, and the difference between the addition and removal payloads is deliberate: `MEMBER_BEING_ADDED` and `MEMBER_ADDED` describe one member with `userId`, while `MEMBER_REMOVED` carries `userIds`, because a removal can cover several members at once. Let the handler's inferred parameter type guide you.
|
|
142
143
|
|
|
144
|
+
`MemberChangeHookPayload` extends `MemberHookPayload` with `previousIsTenantOwner`, `null` for a new membership. An invitation acceptance carries its `deliveryId` and is vetoed before the acceptance is persisted, including on replay: a `deliveryId` is not a policy exemption.
|
|
145
|
+
|
|
143
146
|
`UserDeletedHookPayload.tenantIds` lists the workspaces the user was a member of, all left before the deletion; delete the per-user rows your module keeps in them. `reason` is `"self"` today, the user deleting their own account.
|
|
144
147
|
|
|
145
148
|
`InviteCreatedHookPayload` carries the invite `token`. It is a signup credential: keep it inside the handler rather than forwarding it to a wider surface.
|
|
@@ -60,7 +60,7 @@ Within `types`, four modules are outside that subpath's barrel and are imported
|
|
|
60
60
|
- **Forms from typed fields** — A field names a `DataType`, and the type supplies both the input component and the Zod schema; `Form` compiles the field list into one schema and ships its JSON Schema form with the component.
|
|
61
61
|
- **Tables from data controllers** — `TableView` reads a controller's data-api metadata and its `@Column` declarations to build the columns, the `new` / `edit` / `view` forms, and the permission-carrying actions in one call.
|
|
62
62
|
- **Server-enforced row rules and guards** — Row-action rules are a small algebra evaluated on both sides, and guards run inside the mutating routes, so what the row menu offers is what the server accepts.
|
|
63
|
-
- **A chart and widget set with a shared period scope** —
|
|
63
|
+
- **A chart and widget set with a shared period scope** — Thirteen chart types plus KPI, chart and top-list cards; one `PeriodSelector` id ties them to the same range and comparison.
|
|
64
64
|
- **Layout without a frontend build** — Grids, stacks, tabs and page layouts arrange components, and `CustomComponent` names a Vue component when the vocabulary runs out.
|
|
65
65
|
- **An extensible data-type registry** — `@RegisterDataType` and `@RegisterDataCompareMode` add your own types and filter operators to the catalogue the forms, columns and filters draw from.
|
|
66
66
|
- **Shared prop vocabulary** — Colours, sizes, HTTP methods, action targets, readonly behaviour and watch actions are declared once in `types` and reused by every component.
|
package/docs/3.base/6.layout.md
CHANGED
|
@@ -9,6 +9,13 @@ description: "Grid, stacks, tabs, guard, placeholder and the page layouts that h
|
|
|
9
9
|
|
|
10
10
|
Layout components hold other components. They come in two kinds.
|
|
11
11
|
|
|
12
|
+
| What you want to change | Use |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| The frame around a page: dashboard, settings, or no navigation | A page layout (`DefaultLayout`, `SettingsLayout`, `EmptyLayout`). |
|
|
15
|
+
| The arrangement of blocks inside the page | A container builder (`Grid`, stacks, or tabs). |
|
|
16
|
+
|
|
17
|
+
See the [settings-page screenshot](/docs/building/settings-pages) for the frame and the [container previews](/docs/components/layout-and-containers) for the blocks inside it. The reference below gives their exact contracts.
|
|
18
|
+
|
|
12
19
|
**Containers** are builders: `Grid`, `GridRow`, `HStack`, `VStack`, `Spacer`, `Tab`, `Guard` and `Placeholder` return a `ComponentBuilder`, and you nest components inside them with `.child(id, component)`. They are assigned to a static field of a page class like any other component.
|
|
13
20
|
|
|
14
21
|
**Page layouts** are not builders: `DefaultLayout`, `FormPageLayout`, `SettingsLayout` and `EmptyLayout` return a plain `ComponentInfo` and are passed as the third argument of `PageController` — or as the `layout` option of a page or category, the default of everything declared under it — to say how the page's chrome is drawn.
|
|
@@ -428,4 +435,3 @@ Since the return value is an ordinary builder, `.options()`, `.child()`, `.meta(
|
|
|
428
435
|
`CustomComponent` is also how a table view's `formContainer.pages.*.customPage` option is used: you register your own page carrying a custom component at the slug the table view would otherwise generate — declare that slug as the entry's `urlSlug`, which is taken relative to the page as it stands — see [Tables](/docs/interfaces/base/tables).
|
|
429
436
|
|
|
430
437
|
## Next Steps
|
|
431
|
-
|
|
@@ -13,6 +13,8 @@ The taxonomy is two levels deep. A **category** groups related notifications, a
|
|
|
13
13
|
|
|
14
14
|
Both levels are declared at import time: `NotificationCategory()` first, then the `NotificationSubject()` calls that sit under it. Sending is a fluent chain: `Notification()` opens a builder, the setters fill in the icon, title, description and subject, and `.build()` returns an immutable `SendableNotification` you dispatch to one user, a list of users, the holders of a set of roles, or everyone.
|
|
15
15
|
|
|
16
|
+
See the [notification bell before and after reading](/docs/auth-and-tenancy/authentication#read-notifications) and the [category and subject preferences](/docs/auth-and-tenancy/authentication#notification-preferences) for real dashboard examples. The demonstration sends to one disposable account and checks a second session of that account; it does not broadcast or send email.
|
|
17
|
+
|
|
16
18
|
## Key Features
|
|
17
19
|
|
|
18
20
|
- **Two-level taxonomy** — Categories group subjects, and subjects classify notifications; the `categoryId:subjectId` pair is the key a user's preferences are stored under.
|
|
@@ -13,6 +13,8 @@ You declare categories and subjects by calling `NotificationCategory()` and `Not
|
|
|
13
13
|
|
|
14
14
|
Declarations are values, not decorators: they run when the module that contains them is imported. Declare them at the top level of a module that is imported during startup, so the taxonomy is complete before the first notification is sent.
|
|
15
15
|
|
|
16
|
+
The [notification preferences walkthrough](/docs/auth-and-tenancy/authentication#notification-preferences) shows the System category expanded, its locked General subject, and the Playground category and subject switched off. The Email column is marked Soon: these controls currently manage in-app delivery, not transactional authentication emails.
|
|
17
|
+
|
|
16
18
|
## Declaring a Category
|
|
17
19
|
|
|
18
20
|
`NotificationCategory(id, category)` registers a category and returns the resulting `NotificationCategoryInfo`.
|
|
@@ -9,6 +9,8 @@ description: "Build a notification, then send it to users, roles or everyone, wi
|
|
|
9
9
|
|
|
10
10
|
Sending happens in two steps. `Notification()` starts a builder you fill field by field; `.build()` closes it and gives you a `SendableNotification`, which carries the dispatch methods.
|
|
11
11
|
|
|
12
|
+
For the visible result, see the [single-recipient notification and second-session update](/docs/auth-and-tenancy/authentication#read-notifications). The walkthrough distinguishes delivery from read state and shows [a disabled subject preventing a new delivery](/docs/auth-and-tenancy/authentication#notification-preferences).
|
|
13
|
+
|
|
12
14
|
```typescript
|
|
13
15
|
import {
|
|
14
16
|
GeneralSubject,
|
|
@@ -332,6 +332,20 @@ The `head` slot adds elements to the document head (a `<title>`, a viewport `<me
|
|
|
332
332
|
|
|
333
333
|
The logo is `branding.logo.email.light` from the app config, or `branding.logo.default.light` without an email logo, made absolute against `public.dms.clientBaseUrl` when it starts with `/`. A recipient's mail client fetches it from the internet, and Gmail and Outlook refuse SVG: with `publicLogoOnly`, the layout leaves the logo out when it is an SVG, is not an `http(s)` URL, or is served from a host a mail client cannot reach (`localhost`, `*.local`, `*.internal`, a loopback, private or link-local address), rather than drawing a broken image. Set a PNG logo and a public `clientBaseUrl` for it to show. A `branding.logo.email.dark` goes through the same rules and, when it differs from the light one, is offered to the mail clients in dark mode: the logo is then drawn as `<picture><source media="(prefers-color-scheme: dark)" srcset="…"><img …></picture>`, and a client that ignores the source draws the light image. The same check is exported as `emailLogoUrl(logoPath, clientBaseUrl)` from `#dms-layout/app/emails/components/index`, for a template that draws its own header.
|
|
334
334
|
|
|
335
|
+
### A rendered custom digest
|
|
336
|
+
|
|
337
|
+
The playground's `EmailPlaygroundDigest` reuses this layout with a preheader, `divider="false"` and `public-logo-only`. Here is its actual rendered HTML in English, with fictitious activity for Alex Morgan. With the default SVG logo, the header image is intentionally absent.
|
|
338
|
+
|
|
339
|
+

|
|
340
|
+
|
|
341
|
+
The same template below uses two demonstration PNG logos supplied through the app config. The light-mode capture selects the teal logo; the dark-mode capture selects the navy logo. The reserved demo hostname is mapped to a local image server for these captures, so they do not establish that a recipient can fetch the logo from the internet.
|
|
342
|
+
|
|
343
|
+

|
|
344
|
+
|
|
345
|
+

|
|
346
|
+
|
|
347
|
+
Dark mode changes the selected logo, not the card: `EmailLayout` keeps its white card and pale background in both browser modes. Without a dark logo source, the unbranded examples look identical in both modes. These captures use the real frontend render endpoint and show the returned HTML directly, not the playground's code viewer. No email is sent. Mail clients may strip `<picture>`, block remote images or transform colors; test delivery and appearance in your target clients separately.
|
|
348
|
+
|
|
335
349
|
## Sending Rendered HTML as Email
|
|
336
350
|
|
|
337
351
|
Rendering and sending are separate steps. Render with `GenerateHtml`, then hand the string to the standard AntelopeJS email interface, which needs an implementing module (such as `@antelopejs/nodemailer`) loaded in your project configuration.
|
|
@@ -39,6 +39,56 @@ What the backend passes to each template. A template that replaces a built-in on
|
|
|
39
39
|
|
|
40
40
|
`userName` is the user's name, or their email address when they have none. `expiresInHours` is the lifetime as a number, for the template to word in the recipient's language; `expiresIn` is the same lifetime already worded in English (`24 hours`), kept for templates written before `expiresInHours`.
|
|
41
41
|
|
|
42
|
+
## Rendered examples
|
|
43
|
+
|
|
44
|
+
These captures show HTML returned by the DMS frontend's real render endpoint, opened directly in Chromium, rather than the playground's HTML code viewer. All names, codes, addresses and links are fictitious; no email is sent. The default SVG logo is intentionally omitted by `publicLogoOnly`.
|
|
45
|
+
|
|
46
|
+
### EmailUserValidation
|
|
47
|
+
|
|
48
|
+
The signup email asks Alex to verify their address with a six-digit code, valid for 24 hours.
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
### EmailResetPassword
|
|
53
|
+
|
|
54
|
+
The password-reset email uses a separate code and the configured recovery lifetime: two hours in this example.
|
|
55
|
+
|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
### EmailTwoFactor
|
|
59
|
+
|
|
60
|
+
The second-factor email provides a sign-in code. Its footer tells the recipient to ignore the message if they did not attempt to sign in.
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
### EmailAdminInvite
|
|
65
|
+
|
|
66
|
+
The invitation names the inviter, workspace and platform when they are known. Its button uses a fictitious destination here.
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
### EmailChangeVerification
|
|
71
|
+
|
|
72
|
+
The new address receives the code that confirms the sign-in email change.
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
### EmailChangeNotice
|
|
77
|
+
|
|
78
|
+
The current address receives a notice, not the confirmation code. It tells the recipient what to do if they did not request the change.
|
|
79
|
+
|
|
80
|
+

|
|
81
|
+
|
|
82
|
+
### EmailExportReady
|
|
83
|
+
|
|
84
|
+
A complete export provides a download button and an expiry. A partial export also names the sources that could not be included.
|
|
85
|
+
|
|
86
|
+

|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
These are browser previews, not Gmail, Outlook or Apple Mail compatibility tests. See [Email Layout](/docs/interfaces/html-render/introduction#email-layout) for the custom digest, logo variants and the limits of dark-mode support.
|
|
91
|
+
|
|
42
92
|
## Language
|
|
43
93
|
|
|
44
94
|
Each email is written in the recipient's language: the account's `language`, or for an invitation the language it was sent in. English and French are supported; any other language falls back to English.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/index.md
CHANGED
|
@@ -19,6 +19,15 @@ The DMS ships one public AntelopeJS interface package, `@antelopejs/interface-dm
|
|
|
19
19
|
|
|
20
20
|
This section is the contract reference: the exact symbol names, options and return types, grouped by domain. The DMS guide covers the same ground task by task, organised around what you are building.
|
|
21
21
|
|
|
22
|
+
If you are learning the DMS, start with the [Quickstart](/docs/getting-started/quickstart) and [Pages & components](/docs/building/pages-and-components). Return here when you need an import path, a signature, or the exact behavior of an option; you do not need to read every domain before building a page.
|
|
23
|
+
|
|
24
|
+
| Task | Guide with examples | Contract reference |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| Build a page and choose its layout | [Pages & components](/docs/building/pages-and-components) | [Pages and modules](/docs/interfaces/core/pages-and-modules), [Layout](/docs/interfaces/base/layout) |
|
|
27
|
+
| Add workspace settings | [Settings pages](/docs/building/settings-pages) | [Page access](/docs/interfaces/core/pages-and-modules#page-access) |
|
|
28
|
+
| Protect a route and scope its data | [Auth & tenancy](/docs/auth-and-tenancy/overview) | [Authentication](/docs/interfaces/auth/authentication), [Tenancy](/docs/interfaces/core/tenancy) |
|
|
29
|
+
| Extend another module's screen | [Page extensions](/docs/building/pages-and-components#extending-another-modules-page) | [Extend a page](/docs/interfaces/core/pages-and-modules#extend-a-page-from-another-module) |
|
|
30
|
+
|
|
22
31
|
Separately published extension interfaces have their own [module interface references](/docs/modules#interface-references), including Builder. This page covers `@antelopejs/interface-dms` itself.
|
|
23
32
|
|
|
24
33
|
## One installed copy
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antelopejs/interface-dms",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Public AntelopeJS interfaces of the DMS: pages, components, permissions, tenancy, auth, notifications and HTML rendering.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"antelopejs",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "rimraf dist && tsc",
|
|
35
35
|
"typecheck": "tsc --noEmit",
|
|
36
|
+
"test": "pnpm run build && node --test tests/*.test.cjs",
|
|
36
37
|
"lint": "oxlint && oxfmt --check .",
|
|
37
38
|
"lint:fix": "oxlint --fix --max-warnings=1000000 && oxfmt .",
|
|
38
39
|
"format": "oxfmt .",
|