@fabricorg/archetypes 0.2.0
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 +19 -0
- package/LICENSE +21 -0
- package/README.md +27 -0
- package/dist/index.cjs +177 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +52 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @fabricorg/archetypes
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add the optional Party, Offering, Agreement, Resource, Activity, and Settlement vocabulary with typed
|
|
8
|
+
annotations, conformance reports, explicit startup assertion, and a compiler adapter contract.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @fabricorg/platform@0.11.0
|
|
15
|
+
|
|
16
|
+
## 0.1.0
|
|
17
|
+
|
|
18
|
+
- Add six pre-1.0 archetype definitions, typed semantic annotations, conformance reports, startup
|
|
19
|
+
assertion, and compiler adapter contract.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fabric
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# `@fabricorg/archetypes`
|
|
2
|
+
|
|
3
|
+
Optional, versioned cross-industry archetypes for Fabric module manifests: Party, Offering, Agreement,
|
|
4
|
+
Resource, Activity, and Settlement.
|
|
5
|
+
|
|
6
|
+
The package owns typed namespaced annotations and conformance. `@fabricorg/platform` remains unaware
|
|
7
|
+
of archetype names.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { archetypeSemantics, assertArchetypeConformance } from "@fabricorg/archetypes";
|
|
11
|
+
|
|
12
|
+
const objectType = {
|
|
13
|
+
type: "ServiceVisit",
|
|
14
|
+
semantics: archetypeSemantics({
|
|
15
|
+
id: "fabric.Activity",
|
|
16
|
+
version: "0.1",
|
|
17
|
+
stateMap: { planned: "planned", working: "executing", done: "completed" },
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
assertArchetypeConformance(module);
|
|
22
|
+
registerFabricModules([module]);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Use `validateArchetypeConformance` for report-only build tooling. Use
|
|
26
|
+
`assertArchetypeConformance` explicitly before Platform registration when startup enforcement is
|
|
27
|
+
required. Base Platform registration never interprets archetype annotations.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ARCHETYPES: () => ARCHETYPES,
|
|
24
|
+
ARCHETYPE_SEMANTIC_KEY: () => ARCHETYPE_SEMANTIC_KEY,
|
|
25
|
+
archetypeConformanceAdapter: () => archetypeConformanceAdapter,
|
|
26
|
+
archetypeSemantics: () => archetypeSemantics,
|
|
27
|
+
assertArchetypeConformance: () => assertArchetypeConformance,
|
|
28
|
+
readArchetypeReference: () => readArchetypeReference,
|
|
29
|
+
validateArchetypeConformance: () => validateArchetypeConformance
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
32
|
+
var import_platform = require("@fabricorg/platform");
|
|
33
|
+
var ARCHETYPE_SEMANTIC_KEY = "fabric.archetype";
|
|
34
|
+
var states = (definitions) => Object.fromEntries(definitions.map(([id, stateClass]) => [id, { id, stateClass }]));
|
|
35
|
+
var ARCHETYPES = {
|
|
36
|
+
"fabric.Party": {
|
|
37
|
+
id: "fabric.Party",
|
|
38
|
+
version: "0.1",
|
|
39
|
+
description: "A person or organization participating in business relationships.",
|
|
40
|
+
states: states([["prospective", "initial"], ["active", "active"], ["inactive", "terminal"], ["exception", "exception"]]),
|
|
41
|
+
transitions: [{ from: "prospective", to: "active", required: true }, { from: "active", to: "inactive" }, { from: "prospective", to: "exception" }, { from: "active", to: "exception" }],
|
|
42
|
+
obligations: ["identity is tenant-scoped", "participation is attributable"]
|
|
43
|
+
},
|
|
44
|
+
"fabric.Offering": {
|
|
45
|
+
id: "fabric.Offering",
|
|
46
|
+
version: "0.1",
|
|
47
|
+
description: "Something a party makes available under defined terms.",
|
|
48
|
+
states: states([["available", "active"], ["retired", "terminal"], ["exception", "exception"]]),
|
|
49
|
+
transitions: [{ from: "available", to: "retired" }, { from: "available", to: "exception" }],
|
|
50
|
+
obligations: ["terms are identifiable", "availability is explicit"]
|
|
51
|
+
},
|
|
52
|
+
"fabric.Agreement": {
|
|
53
|
+
id: "fabric.Agreement",
|
|
54
|
+
version: "0.1",
|
|
55
|
+
description: "A governed commitment between parties.",
|
|
56
|
+
states: states([["proposed", "initial"], ["committed", "active"], ["resolved", "terminal"], ["exception", "exception"]]),
|
|
57
|
+
transitions: [{ from: "proposed", to: "committed", required: true }, { from: "committed", to: "resolved", required: true }, { from: "proposed", to: "exception" }, { from: "committed", to: "exception" }],
|
|
58
|
+
obligations: ["participating parties are attributable", "commitment and resolution are auditable"]
|
|
59
|
+
},
|
|
60
|
+
"fabric.Resource": {
|
|
61
|
+
id: "fabric.Resource",
|
|
62
|
+
version: "0.1",
|
|
63
|
+
description: "A capacity or asset allocated by activities.",
|
|
64
|
+
states: states([["available", "initial"], ["allocated", "active"], ["retired", "terminal"], ["exception", "exception"]]),
|
|
65
|
+
transitions: [{ from: "available", to: "allocated", required: true }, { from: "allocated", to: "available" }, { from: "available", to: "retired" }, { from: "allocated", to: "exception" }],
|
|
66
|
+
obligations: ["allocation is identifiable", "conflicting allocation is governed"]
|
|
67
|
+
},
|
|
68
|
+
"fabric.Activity": {
|
|
69
|
+
id: "fabric.Activity",
|
|
70
|
+
version: "0.1",
|
|
71
|
+
description: "Work planned and performed toward an outcome.",
|
|
72
|
+
states: states([["planned", "initial"], ["executing", "active"], ["waiting", "waiting"], ["completed", "terminal"], ["exception", "exception"]]),
|
|
73
|
+
transitions: [{ from: "planned", to: "executing", required: true }, { from: "executing", to: "waiting" }, { from: "waiting", to: "executing" }, { from: "executing", to: "completed", required: true }, { from: "waiting", to: "completed" }, { from: "planned", to: "exception" }, { from: "executing", to: "exception" }, { from: "waiting", to: "exception" }],
|
|
74
|
+
obligations: ["responsible party is attributable", "resource use and outcome are auditable"]
|
|
75
|
+
},
|
|
76
|
+
"fabric.Settlement": {
|
|
77
|
+
id: "fabric.Settlement",
|
|
78
|
+
version: "0.1",
|
|
79
|
+
description: "Resolution of value exchange associated with an agreement.",
|
|
80
|
+
states: states([["pending", "initial"], ["settled", "terminal"], ["reversed", "terminal"], ["exception", "exception"]]),
|
|
81
|
+
transitions: [{ from: "pending", to: "settled", required: true }, { from: "settled", to: "reversed" }, { from: "pending", to: "exception" }],
|
|
82
|
+
obligations: ["value and currency are explicit", "settlement is attributable to an agreement"]
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
function archetypeSemantics(reference) {
|
|
86
|
+
return { [ARCHETYPE_SEMANTIC_KEY]: reference };
|
|
87
|
+
}
|
|
88
|
+
function readArchetypeReference(objectType) {
|
|
89
|
+
const value = objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY];
|
|
90
|
+
if (value === void 0) return void 0;
|
|
91
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
92
|
+
const record = value;
|
|
93
|
+
if (typeof record.id !== "string" || typeof record.version !== "string" || !record.stateMap || typeof record.stateMap !== "object" || Array.isArray(record.stateMap)) return void 0;
|
|
94
|
+
if (!Object.values(record.stateMap).every((state) => typeof state === "string")) return void 0;
|
|
95
|
+
return { id: record.id, version: record.version, stateMap: record.stateMap };
|
|
96
|
+
}
|
|
97
|
+
var transitionKey = (from, to) => `${from}->${to}`;
|
|
98
|
+
function validateArchetypeConformance(manifest) {
|
|
99
|
+
return manifest.objectTypes.filter((objectType) => objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY] !== void 0).map((objectType) => validateObject(manifest, objectType));
|
|
100
|
+
}
|
|
101
|
+
function validateObject(manifest, objectType) {
|
|
102
|
+
const findings = [];
|
|
103
|
+
const reference = readArchetypeReference(objectType);
|
|
104
|
+
if (!reference) {
|
|
105
|
+
findings.push({ code: "invalid_annotation", objectType: objectType.type, message: `Object "${objectType.type}" has an invalid ${ARCHETYPE_SEMANTIC_KEY} annotation.` });
|
|
106
|
+
return { conforms: false, objectType: objectType.type, findings };
|
|
107
|
+
}
|
|
108
|
+
const definition = ARCHETYPES[reference.id];
|
|
109
|
+
if (!definition) {
|
|
110
|
+
findings.push({ code: "unknown_archetype", objectType: objectType.type, message: `Unknown archetype "${reference.id}".` });
|
|
111
|
+
return { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
112
|
+
}
|
|
113
|
+
if (reference.version !== definition.version) {
|
|
114
|
+
findings.push({ code: "unsupported_archetype_version", objectType: objectType.type, message: `Archetype "${reference.id}" supports version ${definition.version}, received ${reference.version}.` });
|
|
115
|
+
}
|
|
116
|
+
const machine = (manifest.stateMachines ?? []).find((candidate) => candidate.entityType === objectType.type);
|
|
117
|
+
if (!machine) {
|
|
118
|
+
findings.push({ code: "missing_state_machine", objectType: objectType.type, message: `Object "${objectType.type}" needs a state machine for archetype conformance.` });
|
|
119
|
+
return { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
120
|
+
}
|
|
121
|
+
for (const state of machine.states) {
|
|
122
|
+
const mapped = reference.stateMap[state.id];
|
|
123
|
+
if (!mapped) {
|
|
124
|
+
findings.push({ code: "unmapped_state", objectType: objectType.type, state: state.id, message: `State "${state.id}" is not mapped.` });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const base = definition.states[mapped];
|
|
128
|
+
if (!base) {
|
|
129
|
+
findings.push({ code: "unknown_archetype_state", objectType: objectType.type, state: state.id, target: mapped, message: `State "${state.id}" maps to unknown archetype state "${mapped}".` });
|
|
130
|
+
} else if (base.stateClass !== state.stateClass) {
|
|
131
|
+
findings.push({ code: "incompatible_state_class", objectType: objectType.type, state: state.id, target: mapped, message: `State "${state.id}" (${state.stateClass}) is incompatible with "${mapped}" (${base.stateClass}).` });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const permitted = new Set(definition.transitions.map((transition) => transitionKey(transition.from, transition.to)));
|
|
135
|
+
const realized = /* @__PURE__ */ new Set();
|
|
136
|
+
for (const transition of machine.transitions) {
|
|
137
|
+
const from = reference.stateMap[transition.from];
|
|
138
|
+
const to = reference.stateMap[transition.to];
|
|
139
|
+
if (!from || !to) continue;
|
|
140
|
+
if (to === "exception" && !transition.hasGuard) {
|
|
141
|
+
findings.push({ code: "exception_transition_unguarded", objectType: objectType.type, state: transition.from, target: transition.to, message: `Exception transition "${transition.from}" -> "${transition.to}" must declare a governance guard.` });
|
|
142
|
+
}
|
|
143
|
+
if (from !== to && !permitted.has(transitionKey(from, to))) {
|
|
144
|
+
findings.push({ code: "transition_not_permitted", objectType: objectType.type, state: transition.from, target: transition.to, message: `Transition "${transition.from}" -> "${transition.to}" maps to disallowed archetype transition "${from}" -> "${to}".` });
|
|
145
|
+
} else if (from !== to) {
|
|
146
|
+
realized.add(transitionKey(from, to));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const required of definition.transitions.filter((transition) => transition.required)) {
|
|
150
|
+
if (!realized.has(transitionKey(required.from, required.to))) {
|
|
151
|
+
findings.push({ code: "required_transition_unreachable", objectType: objectType.type, state: required.from, target: required.to, message: `Required archetype transition "${required.from}" -> "${required.to}" is not realized.` });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { conforms: findings.length === 0, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
155
|
+
}
|
|
156
|
+
function assertArchetypeConformance(module2) {
|
|
157
|
+
const failures = validateArchetypeConformance((0, import_platform.exportModuleManifest)(module2)).filter((report) => !report.conforms);
|
|
158
|
+
if (failures.length > 0) {
|
|
159
|
+
throw new Error(`Archetype conformance failed:
|
|
160
|
+
${failures.flatMap((report) => report.findings.map((finding) => `- ${report.objectType}: ${finding.message}`)).join("\n")}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
var archetypeConformanceAdapter = {
|
|
164
|
+
id: "@fabricorg/archetypes",
|
|
165
|
+
evaluate: validateArchetypeConformance
|
|
166
|
+
};
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
ARCHETYPES,
|
|
170
|
+
ARCHETYPE_SEMANTIC_KEY,
|
|
171
|
+
archetypeConformanceAdapter,
|
|
172
|
+
archetypeSemantics,
|
|
173
|
+
assertArchetypeConformance,
|
|
174
|
+
readArchetypeReference,
|
|
175
|
+
validateArchetypeConformance
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import {\n\texportModuleManifest,\n\ttype FabricModule,\n\ttype JsonValue,\n\ttype ModuleManifest,\n\ttype ModuleManifestObjectType,\n\ttype StateClass,\n} from \"@fabricorg/platform\";\n\nexport const ARCHETYPE_SEMANTIC_KEY = \"fabric.archetype\" as const;\n\nexport type ArchetypeId =\n\t| \"fabric.Party\"\n\t| \"fabric.Offering\"\n\t| \"fabric.Agreement\"\n\t| \"fabric.Resource\"\n\t| \"fabric.Activity\"\n\t| \"fabric.Settlement\";\n\nexport interface ArchetypeReference {\n\tid: ArchetypeId;\n\tversion: string;\n\tstateMap: Record<string, string>;\n}\n\nexport interface ArchetypeState {\n\tid: string;\n\tstateClass: StateClass;\n}\n\nexport interface ArchetypeTransition {\n\tfrom: string;\n\tto: string;\n\trequired?: boolean;\n}\n\nexport interface ArchetypeDefinition {\n\tid: ArchetypeId;\n\tversion: string;\n\tdescription: string;\n\tstates: Record<string, ArchetypeState>;\n\ttransitions: ArchetypeTransition[];\n\tobligations: string[];\n}\n\nexport type ConformanceFindingCode =\n\t| \"invalid_annotation\"\n\t| \"unknown_archetype\"\n\t| \"unsupported_archetype_version\"\n\t| \"missing_state_machine\"\n\t| \"unmapped_state\"\n\t| \"unknown_archetype_state\"\n\t| \"incompatible_state_class\"\n\t| \"transition_not_permitted\"\n\t| \"exception_transition_unguarded\"\n\t| \"required_transition_unreachable\";\n\nexport interface ConformanceFinding {\n\tcode: ConformanceFindingCode;\n\tmessage: string;\n\tobjectType: string;\n\tstate?: string;\n\ttarget?: string;\n}\n\nexport interface ArchetypeConformanceReport {\n\tconforms: boolean;\n\tobjectType: string;\n\tarchetype?: string;\n\tfindings: ConformanceFinding[];\n}\n\nexport interface ManifestConformanceAdapter {\n\tid: string;\n\tevaluate(manifest: ModuleManifest): ArchetypeConformanceReport[];\n}\n\nconst states = (definitions: Array<[string, StateClass]>): Record<string, ArchetypeState> =>\n\tObject.fromEntries(definitions.map(([id, stateClass]) => [id, { id, stateClass }]));\n\nexport const ARCHETYPES: Readonly<Record<ArchetypeId, ArchetypeDefinition>> = {\n\t\"fabric.Party\": {\n\t\tid: \"fabric.Party\", version: \"0.1\", description: \"A person or organization participating in business relationships.\",\n\t\tstates: states([[\"prospective\", \"initial\"], [\"active\", \"active\"], [\"inactive\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"prospective\", to: \"active\", required: true }, { from: \"active\", to: \"inactive\" }, { from: \"prospective\", to: \"exception\" }, { from: \"active\", to: \"exception\" }],\n\t\tobligations: [\"identity is tenant-scoped\", \"participation is attributable\"],\n\t},\n\t\"fabric.Offering\": {\n\t\tid: \"fabric.Offering\", version: \"0.1\", description: \"Something a party makes available under defined terms.\",\n\t\tstates: states([[\"available\", \"active\"], [\"retired\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"available\", to: \"retired\" }, { from: \"available\", to: \"exception\" }],\n\t\tobligations: [\"terms are identifiable\", \"availability is explicit\"],\n\t},\n\t\"fabric.Agreement\": {\n\t\tid: \"fabric.Agreement\", version: \"0.1\", description: \"A governed commitment between parties.\",\n\t\tstates: states([[\"proposed\", \"initial\"], [\"committed\", \"active\"], [\"resolved\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"proposed\", to: \"committed\", required: true }, { from: \"committed\", to: \"resolved\", required: true }, { from: \"proposed\", to: \"exception\" }, { from: \"committed\", to: \"exception\" }],\n\t\tobligations: [\"participating parties are attributable\", \"commitment and resolution are auditable\"],\n\t},\n\t\"fabric.Resource\": {\n\t\tid: \"fabric.Resource\", version: \"0.1\", description: \"A capacity or asset allocated by activities.\",\n\t\tstates: states([[\"available\", \"initial\"], [\"allocated\", \"active\"], [\"retired\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"available\", to: \"allocated\", required: true }, { from: \"allocated\", to: \"available\" }, { from: \"available\", to: \"retired\" }, { from: \"allocated\", to: \"exception\" }],\n\t\tobligations: [\"allocation is identifiable\", \"conflicting allocation is governed\"],\n\t},\n\t\"fabric.Activity\": {\n\t\tid: \"fabric.Activity\", version: \"0.1\", description: \"Work planned and performed toward an outcome.\",\n\t\tstates: states([[\"planned\", \"initial\"], [\"executing\", \"active\"], [\"waiting\", \"waiting\"], [\"completed\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"planned\", to: \"executing\", required: true }, { from: \"executing\", to: \"waiting\" }, { from: \"waiting\", to: \"executing\" }, { from: \"executing\", to: \"completed\", required: true }, { from: \"waiting\", to: \"completed\" }, { from: \"planned\", to: \"exception\" }, { from: \"executing\", to: \"exception\" }, { from: \"waiting\", to: \"exception\" }],\n\t\tobligations: [\"responsible party is attributable\", \"resource use and outcome are auditable\"],\n\t},\n\t\"fabric.Settlement\": {\n\t\tid: \"fabric.Settlement\", version: \"0.1\", description: \"Resolution of value exchange associated with an agreement.\",\n\t\tstates: states([[\"pending\", \"initial\"], [\"settled\", \"terminal\"], [\"reversed\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"pending\", to: \"settled\", required: true }, { from: \"settled\", to: \"reversed\" }, { from: \"pending\", to: \"exception\" }],\n\t\tobligations: [\"value and currency are explicit\", \"settlement is attributable to an agreement\"],\n\t},\n};\n\nexport function archetypeSemantics(reference: ArchetypeReference): Record<string, JsonValue> {\n\treturn { [ARCHETYPE_SEMANTIC_KEY]: reference as unknown as JsonValue };\n}\n\nexport function readArchetypeReference(\n\tobjectType: ModuleManifestObjectType,\n): ArchetypeReference | undefined {\n\tconst value = objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY];\n\tif (value === undefined) return undefined;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst record = value as Record<string, JsonValue>;\n\tif (typeof record.id !== \"string\" || typeof record.version !== \"string\" || !record.stateMap || typeof record.stateMap !== \"object\" || Array.isArray(record.stateMap)) return undefined;\n\tif (!Object.values(record.stateMap).every((state) => typeof state === \"string\")) return undefined;\n\treturn { id: record.id as ArchetypeId, version: record.version, stateMap: record.stateMap as Record<string, string> };\n}\n\nconst transitionKey = (from: string, to: string) => `${from}->${to}`;\n\nexport function validateArchetypeConformance(\n\tmanifest: ModuleManifest,\n): ArchetypeConformanceReport[] {\n\treturn manifest.objectTypes\n\t\t.filter((objectType) => objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY] !== undefined)\n\t\t.map((objectType) => validateObject(manifest, objectType));\n}\n\nfunction validateObject(\n\tmanifest: ModuleManifest,\n\tobjectType: ModuleManifestObjectType,\n): ArchetypeConformanceReport {\n\tconst findings: ConformanceFinding[] = [];\n\tconst reference = readArchetypeReference(objectType);\n\tif (!reference) {\n\t\tfindings.push({ code: \"invalid_annotation\", objectType: objectType.type, message: `Object \"${objectType.type}\" has an invalid ${ARCHETYPE_SEMANTIC_KEY} annotation.` });\n\t\treturn { conforms: false, objectType: objectType.type, findings };\n\t}\n\tconst definition = ARCHETYPES[reference.id];\n\tif (!definition) {\n\t\tfindings.push({ code: \"unknown_archetype\", objectType: objectType.type, message: `Unknown archetype \"${reference.id}\".` });\n\t\treturn { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n\t}\n\tif (reference.version !== definition.version) {\n\t\tfindings.push({ code: \"unsupported_archetype_version\", objectType: objectType.type, message: `Archetype \"${reference.id}\" supports version ${definition.version}, received ${reference.version}.` });\n\t}\n\tconst machine = (manifest.stateMachines ?? []).find((candidate) => candidate.entityType === objectType.type);\n\tif (!machine) {\n\t\tfindings.push({ code: \"missing_state_machine\", objectType: objectType.type, message: `Object \"${objectType.type}\" needs a state machine for archetype conformance.` });\n\t\treturn { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n\t}\n\tfor (const state of machine.states) {\n\t\tconst mapped = reference.stateMap[state.id];\n\t\tif (!mapped) {\n\t\t\tfindings.push({ code: \"unmapped_state\", objectType: objectType.type, state: state.id, message: `State \"${state.id}\" is not mapped.` });\n\t\t\tcontinue;\n\t\t}\n\t\tconst base = definition.states[mapped];\n\t\tif (!base) {\n\t\t\tfindings.push({ code: \"unknown_archetype_state\", objectType: objectType.type, state: state.id, target: mapped, message: `State \"${state.id}\" maps to unknown archetype state \"${mapped}\".` });\n\t\t} else if (base.stateClass !== state.stateClass) {\n\t\t\tfindings.push({ code: \"incompatible_state_class\", objectType: objectType.type, state: state.id, target: mapped, message: `State \"${state.id}\" (${state.stateClass}) is incompatible with \"${mapped}\" (${base.stateClass}).` });\n\t\t}\n\t}\n\tconst permitted = new Set(definition.transitions.map((transition) => transitionKey(transition.from, transition.to)));\n\tconst realized = new Set<string>();\n\tfor (const transition of machine.transitions) {\n\t\tconst from = reference.stateMap[transition.from];\n\t\tconst to = reference.stateMap[transition.to];\n\t\tif (!from || !to) continue;\n\t\tif (to === \"exception\" && !transition.hasGuard) {\n\t\t\tfindings.push({ code: \"exception_transition_unguarded\", objectType: objectType.type, state: transition.from, target: transition.to, message: `Exception transition \"${transition.from}\" -> \"${transition.to}\" must declare a governance guard.` });\n\t\t}\n\t\tif (from !== to && !permitted.has(transitionKey(from, to))) {\n\t\t\tfindings.push({ code: \"transition_not_permitted\", objectType: objectType.type, state: transition.from, target: transition.to, message: `Transition \"${transition.from}\" -> \"${transition.to}\" maps to disallowed archetype transition \"${from}\" -> \"${to}\".` });\n\t\t} else if (from !== to) {\n\t\t\trealized.add(transitionKey(from, to));\n\t\t}\n\t}\n\tfor (const required of definition.transitions.filter((transition) => transition.required)) {\n\t\tif (!realized.has(transitionKey(required.from, required.to))) {\n\t\t\tfindings.push({ code: \"required_transition_unreachable\", objectType: objectType.type, state: required.from, target: required.to, message: `Required archetype transition \"${required.from}\" -> \"${required.to}\" is not realized.` });\n\t\t}\n\t}\n\treturn { conforms: findings.length === 0, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n}\n\nexport function assertArchetypeConformance(module: FabricModule<unknown>): void {\n\tconst failures = validateArchetypeConformance(exportModuleManifest(module)).filter((report) => !report.conforms);\n\tif (failures.length > 0) {\n\t\tthrow new Error(`Archetype conformance failed:\\n${failures.flatMap((report) => report.findings.map((finding) => `- ${report.objectType}: ${finding.message}`)).join(\"\\n\")}`);\n\t}\n}\n\nexport const archetypeConformanceAdapter: ManifestConformanceAdapter = {\n\tid: \"@fabricorg/archetypes\",\n\tevaluate: validateArchetypeConformance,\n};\n"],"mappings":"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","names":["module"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StateClass, ModuleManifest, JsonValue, FabricModule, ModuleManifestObjectType } from '@fabricorg/platform';
|
|
2
|
+
|
|
3
|
+
declare const ARCHETYPE_SEMANTIC_KEY: "fabric.archetype";
|
|
4
|
+
type ArchetypeId = "fabric.Party" | "fabric.Offering" | "fabric.Agreement" | "fabric.Resource" | "fabric.Activity" | "fabric.Settlement";
|
|
5
|
+
interface ArchetypeReference {
|
|
6
|
+
id: ArchetypeId;
|
|
7
|
+
version: string;
|
|
8
|
+
stateMap: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
interface ArchetypeState {
|
|
11
|
+
id: string;
|
|
12
|
+
stateClass: StateClass;
|
|
13
|
+
}
|
|
14
|
+
interface ArchetypeTransition {
|
|
15
|
+
from: string;
|
|
16
|
+
to: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface ArchetypeDefinition {
|
|
20
|
+
id: ArchetypeId;
|
|
21
|
+
version: string;
|
|
22
|
+
description: string;
|
|
23
|
+
states: Record<string, ArchetypeState>;
|
|
24
|
+
transitions: ArchetypeTransition[];
|
|
25
|
+
obligations: string[];
|
|
26
|
+
}
|
|
27
|
+
type ConformanceFindingCode = "invalid_annotation" | "unknown_archetype" | "unsupported_archetype_version" | "missing_state_machine" | "unmapped_state" | "unknown_archetype_state" | "incompatible_state_class" | "transition_not_permitted" | "exception_transition_unguarded" | "required_transition_unreachable";
|
|
28
|
+
interface ConformanceFinding {
|
|
29
|
+
code: ConformanceFindingCode;
|
|
30
|
+
message: string;
|
|
31
|
+
objectType: string;
|
|
32
|
+
state?: string;
|
|
33
|
+
target?: string;
|
|
34
|
+
}
|
|
35
|
+
interface ArchetypeConformanceReport {
|
|
36
|
+
conforms: boolean;
|
|
37
|
+
objectType: string;
|
|
38
|
+
archetype?: string;
|
|
39
|
+
findings: ConformanceFinding[];
|
|
40
|
+
}
|
|
41
|
+
interface ManifestConformanceAdapter {
|
|
42
|
+
id: string;
|
|
43
|
+
evaluate(manifest: ModuleManifest): ArchetypeConformanceReport[];
|
|
44
|
+
}
|
|
45
|
+
declare const ARCHETYPES: Readonly<Record<ArchetypeId, ArchetypeDefinition>>;
|
|
46
|
+
declare function archetypeSemantics(reference: ArchetypeReference): Record<string, JsonValue>;
|
|
47
|
+
declare function readArchetypeReference(objectType: ModuleManifestObjectType): ArchetypeReference | undefined;
|
|
48
|
+
declare function validateArchetypeConformance(manifest: ModuleManifest): ArchetypeConformanceReport[];
|
|
49
|
+
declare function assertArchetypeConformance(module: FabricModule<unknown>): void;
|
|
50
|
+
declare const archetypeConformanceAdapter: ManifestConformanceAdapter;
|
|
51
|
+
|
|
52
|
+
export { ARCHETYPES, ARCHETYPE_SEMANTIC_KEY, type ArchetypeConformanceReport, type ArchetypeDefinition, type ArchetypeId, type ArchetypeReference, type ArchetypeState, type ArchetypeTransition, type ConformanceFinding, type ConformanceFindingCode, type ManifestConformanceAdapter, archetypeConformanceAdapter, archetypeSemantics, assertArchetypeConformance, readArchetypeReference, validateArchetypeConformance };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StateClass, ModuleManifest, JsonValue, FabricModule, ModuleManifestObjectType } from '@fabricorg/platform';
|
|
2
|
+
|
|
3
|
+
declare const ARCHETYPE_SEMANTIC_KEY: "fabric.archetype";
|
|
4
|
+
type ArchetypeId = "fabric.Party" | "fabric.Offering" | "fabric.Agreement" | "fabric.Resource" | "fabric.Activity" | "fabric.Settlement";
|
|
5
|
+
interface ArchetypeReference {
|
|
6
|
+
id: ArchetypeId;
|
|
7
|
+
version: string;
|
|
8
|
+
stateMap: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
interface ArchetypeState {
|
|
11
|
+
id: string;
|
|
12
|
+
stateClass: StateClass;
|
|
13
|
+
}
|
|
14
|
+
interface ArchetypeTransition {
|
|
15
|
+
from: string;
|
|
16
|
+
to: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface ArchetypeDefinition {
|
|
20
|
+
id: ArchetypeId;
|
|
21
|
+
version: string;
|
|
22
|
+
description: string;
|
|
23
|
+
states: Record<string, ArchetypeState>;
|
|
24
|
+
transitions: ArchetypeTransition[];
|
|
25
|
+
obligations: string[];
|
|
26
|
+
}
|
|
27
|
+
type ConformanceFindingCode = "invalid_annotation" | "unknown_archetype" | "unsupported_archetype_version" | "missing_state_machine" | "unmapped_state" | "unknown_archetype_state" | "incompatible_state_class" | "transition_not_permitted" | "exception_transition_unguarded" | "required_transition_unreachable";
|
|
28
|
+
interface ConformanceFinding {
|
|
29
|
+
code: ConformanceFindingCode;
|
|
30
|
+
message: string;
|
|
31
|
+
objectType: string;
|
|
32
|
+
state?: string;
|
|
33
|
+
target?: string;
|
|
34
|
+
}
|
|
35
|
+
interface ArchetypeConformanceReport {
|
|
36
|
+
conforms: boolean;
|
|
37
|
+
objectType: string;
|
|
38
|
+
archetype?: string;
|
|
39
|
+
findings: ConformanceFinding[];
|
|
40
|
+
}
|
|
41
|
+
interface ManifestConformanceAdapter {
|
|
42
|
+
id: string;
|
|
43
|
+
evaluate(manifest: ModuleManifest): ArchetypeConformanceReport[];
|
|
44
|
+
}
|
|
45
|
+
declare const ARCHETYPES: Readonly<Record<ArchetypeId, ArchetypeDefinition>>;
|
|
46
|
+
declare function archetypeSemantics(reference: ArchetypeReference): Record<string, JsonValue>;
|
|
47
|
+
declare function readArchetypeReference(objectType: ModuleManifestObjectType): ArchetypeReference | undefined;
|
|
48
|
+
declare function validateArchetypeConformance(manifest: ModuleManifest): ArchetypeConformanceReport[];
|
|
49
|
+
declare function assertArchetypeConformance(module: FabricModule<unknown>): void;
|
|
50
|
+
declare const archetypeConformanceAdapter: ManifestConformanceAdapter;
|
|
51
|
+
|
|
52
|
+
export { ARCHETYPES, ARCHETYPE_SEMANTIC_KEY, type ArchetypeConformanceReport, type ArchetypeDefinition, type ArchetypeId, type ArchetypeReference, type ArchetypeState, type ArchetypeTransition, type ConformanceFinding, type ConformanceFindingCode, type ManifestConformanceAdapter, archetypeConformanceAdapter, archetypeSemantics, assertArchetypeConformance, readArchetypeReference, validateArchetypeConformance };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import {
|
|
3
|
+
exportModuleManifest
|
|
4
|
+
} from "@fabricorg/platform";
|
|
5
|
+
var ARCHETYPE_SEMANTIC_KEY = "fabric.archetype";
|
|
6
|
+
var states = (definitions) => Object.fromEntries(definitions.map(([id, stateClass]) => [id, { id, stateClass }]));
|
|
7
|
+
var ARCHETYPES = {
|
|
8
|
+
"fabric.Party": {
|
|
9
|
+
id: "fabric.Party",
|
|
10
|
+
version: "0.1",
|
|
11
|
+
description: "A person or organization participating in business relationships.",
|
|
12
|
+
states: states([["prospective", "initial"], ["active", "active"], ["inactive", "terminal"], ["exception", "exception"]]),
|
|
13
|
+
transitions: [{ from: "prospective", to: "active", required: true }, { from: "active", to: "inactive" }, { from: "prospective", to: "exception" }, { from: "active", to: "exception" }],
|
|
14
|
+
obligations: ["identity is tenant-scoped", "participation is attributable"]
|
|
15
|
+
},
|
|
16
|
+
"fabric.Offering": {
|
|
17
|
+
id: "fabric.Offering",
|
|
18
|
+
version: "0.1",
|
|
19
|
+
description: "Something a party makes available under defined terms.",
|
|
20
|
+
states: states([["available", "active"], ["retired", "terminal"], ["exception", "exception"]]),
|
|
21
|
+
transitions: [{ from: "available", to: "retired" }, { from: "available", to: "exception" }],
|
|
22
|
+
obligations: ["terms are identifiable", "availability is explicit"]
|
|
23
|
+
},
|
|
24
|
+
"fabric.Agreement": {
|
|
25
|
+
id: "fabric.Agreement",
|
|
26
|
+
version: "0.1",
|
|
27
|
+
description: "A governed commitment between parties.",
|
|
28
|
+
states: states([["proposed", "initial"], ["committed", "active"], ["resolved", "terminal"], ["exception", "exception"]]),
|
|
29
|
+
transitions: [{ from: "proposed", to: "committed", required: true }, { from: "committed", to: "resolved", required: true }, { from: "proposed", to: "exception" }, { from: "committed", to: "exception" }],
|
|
30
|
+
obligations: ["participating parties are attributable", "commitment and resolution are auditable"]
|
|
31
|
+
},
|
|
32
|
+
"fabric.Resource": {
|
|
33
|
+
id: "fabric.Resource",
|
|
34
|
+
version: "0.1",
|
|
35
|
+
description: "A capacity or asset allocated by activities.",
|
|
36
|
+
states: states([["available", "initial"], ["allocated", "active"], ["retired", "terminal"], ["exception", "exception"]]),
|
|
37
|
+
transitions: [{ from: "available", to: "allocated", required: true }, { from: "allocated", to: "available" }, { from: "available", to: "retired" }, { from: "allocated", to: "exception" }],
|
|
38
|
+
obligations: ["allocation is identifiable", "conflicting allocation is governed"]
|
|
39
|
+
},
|
|
40
|
+
"fabric.Activity": {
|
|
41
|
+
id: "fabric.Activity",
|
|
42
|
+
version: "0.1",
|
|
43
|
+
description: "Work planned and performed toward an outcome.",
|
|
44
|
+
states: states([["planned", "initial"], ["executing", "active"], ["waiting", "waiting"], ["completed", "terminal"], ["exception", "exception"]]),
|
|
45
|
+
transitions: [{ from: "planned", to: "executing", required: true }, { from: "executing", to: "waiting" }, { from: "waiting", to: "executing" }, { from: "executing", to: "completed", required: true }, { from: "waiting", to: "completed" }, { from: "planned", to: "exception" }, { from: "executing", to: "exception" }, { from: "waiting", to: "exception" }],
|
|
46
|
+
obligations: ["responsible party is attributable", "resource use and outcome are auditable"]
|
|
47
|
+
},
|
|
48
|
+
"fabric.Settlement": {
|
|
49
|
+
id: "fabric.Settlement",
|
|
50
|
+
version: "0.1",
|
|
51
|
+
description: "Resolution of value exchange associated with an agreement.",
|
|
52
|
+
states: states([["pending", "initial"], ["settled", "terminal"], ["reversed", "terminal"], ["exception", "exception"]]),
|
|
53
|
+
transitions: [{ from: "pending", to: "settled", required: true }, { from: "settled", to: "reversed" }, { from: "pending", to: "exception" }],
|
|
54
|
+
obligations: ["value and currency are explicit", "settlement is attributable to an agreement"]
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
function archetypeSemantics(reference) {
|
|
58
|
+
return { [ARCHETYPE_SEMANTIC_KEY]: reference };
|
|
59
|
+
}
|
|
60
|
+
function readArchetypeReference(objectType) {
|
|
61
|
+
const value = objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY];
|
|
62
|
+
if (value === void 0) return void 0;
|
|
63
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
64
|
+
const record = value;
|
|
65
|
+
if (typeof record.id !== "string" || typeof record.version !== "string" || !record.stateMap || typeof record.stateMap !== "object" || Array.isArray(record.stateMap)) return void 0;
|
|
66
|
+
if (!Object.values(record.stateMap).every((state) => typeof state === "string")) return void 0;
|
|
67
|
+
return { id: record.id, version: record.version, stateMap: record.stateMap };
|
|
68
|
+
}
|
|
69
|
+
var transitionKey = (from, to) => `${from}->${to}`;
|
|
70
|
+
function validateArchetypeConformance(manifest) {
|
|
71
|
+
return manifest.objectTypes.filter((objectType) => objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY] !== void 0).map((objectType) => validateObject(manifest, objectType));
|
|
72
|
+
}
|
|
73
|
+
function validateObject(manifest, objectType) {
|
|
74
|
+
const findings = [];
|
|
75
|
+
const reference = readArchetypeReference(objectType);
|
|
76
|
+
if (!reference) {
|
|
77
|
+
findings.push({ code: "invalid_annotation", objectType: objectType.type, message: `Object "${objectType.type}" has an invalid ${ARCHETYPE_SEMANTIC_KEY} annotation.` });
|
|
78
|
+
return { conforms: false, objectType: objectType.type, findings };
|
|
79
|
+
}
|
|
80
|
+
const definition = ARCHETYPES[reference.id];
|
|
81
|
+
if (!definition) {
|
|
82
|
+
findings.push({ code: "unknown_archetype", objectType: objectType.type, message: `Unknown archetype "${reference.id}".` });
|
|
83
|
+
return { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
84
|
+
}
|
|
85
|
+
if (reference.version !== definition.version) {
|
|
86
|
+
findings.push({ code: "unsupported_archetype_version", objectType: objectType.type, message: `Archetype "${reference.id}" supports version ${definition.version}, received ${reference.version}.` });
|
|
87
|
+
}
|
|
88
|
+
const machine = (manifest.stateMachines ?? []).find((candidate) => candidate.entityType === objectType.type);
|
|
89
|
+
if (!machine) {
|
|
90
|
+
findings.push({ code: "missing_state_machine", objectType: objectType.type, message: `Object "${objectType.type}" needs a state machine for archetype conformance.` });
|
|
91
|
+
return { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
92
|
+
}
|
|
93
|
+
for (const state of machine.states) {
|
|
94
|
+
const mapped = reference.stateMap[state.id];
|
|
95
|
+
if (!mapped) {
|
|
96
|
+
findings.push({ code: "unmapped_state", objectType: objectType.type, state: state.id, message: `State "${state.id}" is not mapped.` });
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const base = definition.states[mapped];
|
|
100
|
+
if (!base) {
|
|
101
|
+
findings.push({ code: "unknown_archetype_state", objectType: objectType.type, state: state.id, target: mapped, message: `State "${state.id}" maps to unknown archetype state "${mapped}".` });
|
|
102
|
+
} else if (base.stateClass !== state.stateClass) {
|
|
103
|
+
findings.push({ code: "incompatible_state_class", objectType: objectType.type, state: state.id, target: mapped, message: `State "${state.id}" (${state.stateClass}) is incompatible with "${mapped}" (${base.stateClass}).` });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const permitted = new Set(definition.transitions.map((transition) => transitionKey(transition.from, transition.to)));
|
|
107
|
+
const realized = /* @__PURE__ */ new Set();
|
|
108
|
+
for (const transition of machine.transitions) {
|
|
109
|
+
const from = reference.stateMap[transition.from];
|
|
110
|
+
const to = reference.stateMap[transition.to];
|
|
111
|
+
if (!from || !to) continue;
|
|
112
|
+
if (to === "exception" && !transition.hasGuard) {
|
|
113
|
+
findings.push({ code: "exception_transition_unguarded", objectType: objectType.type, state: transition.from, target: transition.to, message: `Exception transition "${transition.from}" -> "${transition.to}" must declare a governance guard.` });
|
|
114
|
+
}
|
|
115
|
+
if (from !== to && !permitted.has(transitionKey(from, to))) {
|
|
116
|
+
findings.push({ code: "transition_not_permitted", objectType: objectType.type, state: transition.from, target: transition.to, message: `Transition "${transition.from}" -> "${transition.to}" maps to disallowed archetype transition "${from}" -> "${to}".` });
|
|
117
|
+
} else if (from !== to) {
|
|
118
|
+
realized.add(transitionKey(from, to));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const required of definition.transitions.filter((transition) => transition.required)) {
|
|
122
|
+
if (!realized.has(transitionKey(required.from, required.to))) {
|
|
123
|
+
findings.push({ code: "required_transition_unreachable", objectType: objectType.type, state: required.from, target: required.to, message: `Required archetype transition "${required.from}" -> "${required.to}" is not realized.` });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { conforms: findings.length === 0, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };
|
|
127
|
+
}
|
|
128
|
+
function assertArchetypeConformance(module) {
|
|
129
|
+
const failures = validateArchetypeConformance(exportModuleManifest(module)).filter((report) => !report.conforms);
|
|
130
|
+
if (failures.length > 0) {
|
|
131
|
+
throw new Error(`Archetype conformance failed:
|
|
132
|
+
${failures.flatMap((report) => report.findings.map((finding) => `- ${report.objectType}: ${finding.message}`)).join("\n")}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
var archetypeConformanceAdapter = {
|
|
136
|
+
id: "@fabricorg/archetypes",
|
|
137
|
+
evaluate: validateArchetypeConformance
|
|
138
|
+
};
|
|
139
|
+
export {
|
|
140
|
+
ARCHETYPES,
|
|
141
|
+
ARCHETYPE_SEMANTIC_KEY,
|
|
142
|
+
archetypeConformanceAdapter,
|
|
143
|
+
archetypeSemantics,
|
|
144
|
+
assertArchetypeConformance,
|
|
145
|
+
readArchetypeReference,
|
|
146
|
+
validateArchetypeConformance
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import {\n\texportModuleManifest,\n\ttype FabricModule,\n\ttype JsonValue,\n\ttype ModuleManifest,\n\ttype ModuleManifestObjectType,\n\ttype StateClass,\n} from \"@fabricorg/platform\";\n\nexport const ARCHETYPE_SEMANTIC_KEY = \"fabric.archetype\" as const;\n\nexport type ArchetypeId =\n\t| \"fabric.Party\"\n\t| \"fabric.Offering\"\n\t| \"fabric.Agreement\"\n\t| \"fabric.Resource\"\n\t| \"fabric.Activity\"\n\t| \"fabric.Settlement\";\n\nexport interface ArchetypeReference {\n\tid: ArchetypeId;\n\tversion: string;\n\tstateMap: Record<string, string>;\n}\n\nexport interface ArchetypeState {\n\tid: string;\n\tstateClass: StateClass;\n}\n\nexport interface ArchetypeTransition {\n\tfrom: string;\n\tto: string;\n\trequired?: boolean;\n}\n\nexport interface ArchetypeDefinition {\n\tid: ArchetypeId;\n\tversion: string;\n\tdescription: string;\n\tstates: Record<string, ArchetypeState>;\n\ttransitions: ArchetypeTransition[];\n\tobligations: string[];\n}\n\nexport type ConformanceFindingCode =\n\t| \"invalid_annotation\"\n\t| \"unknown_archetype\"\n\t| \"unsupported_archetype_version\"\n\t| \"missing_state_machine\"\n\t| \"unmapped_state\"\n\t| \"unknown_archetype_state\"\n\t| \"incompatible_state_class\"\n\t| \"transition_not_permitted\"\n\t| \"exception_transition_unguarded\"\n\t| \"required_transition_unreachable\";\n\nexport interface ConformanceFinding {\n\tcode: ConformanceFindingCode;\n\tmessage: string;\n\tobjectType: string;\n\tstate?: string;\n\ttarget?: string;\n}\n\nexport interface ArchetypeConformanceReport {\n\tconforms: boolean;\n\tobjectType: string;\n\tarchetype?: string;\n\tfindings: ConformanceFinding[];\n}\n\nexport interface ManifestConformanceAdapter {\n\tid: string;\n\tevaluate(manifest: ModuleManifest): ArchetypeConformanceReport[];\n}\n\nconst states = (definitions: Array<[string, StateClass]>): Record<string, ArchetypeState> =>\n\tObject.fromEntries(definitions.map(([id, stateClass]) => [id, { id, stateClass }]));\n\nexport const ARCHETYPES: Readonly<Record<ArchetypeId, ArchetypeDefinition>> = {\n\t\"fabric.Party\": {\n\t\tid: \"fabric.Party\", version: \"0.1\", description: \"A person or organization participating in business relationships.\",\n\t\tstates: states([[\"prospective\", \"initial\"], [\"active\", \"active\"], [\"inactive\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"prospective\", to: \"active\", required: true }, { from: \"active\", to: \"inactive\" }, { from: \"prospective\", to: \"exception\" }, { from: \"active\", to: \"exception\" }],\n\t\tobligations: [\"identity is tenant-scoped\", \"participation is attributable\"],\n\t},\n\t\"fabric.Offering\": {\n\t\tid: \"fabric.Offering\", version: \"0.1\", description: \"Something a party makes available under defined terms.\",\n\t\tstates: states([[\"available\", \"active\"], [\"retired\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"available\", to: \"retired\" }, { from: \"available\", to: \"exception\" }],\n\t\tobligations: [\"terms are identifiable\", \"availability is explicit\"],\n\t},\n\t\"fabric.Agreement\": {\n\t\tid: \"fabric.Agreement\", version: \"0.1\", description: \"A governed commitment between parties.\",\n\t\tstates: states([[\"proposed\", \"initial\"], [\"committed\", \"active\"], [\"resolved\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"proposed\", to: \"committed\", required: true }, { from: \"committed\", to: \"resolved\", required: true }, { from: \"proposed\", to: \"exception\" }, { from: \"committed\", to: \"exception\" }],\n\t\tobligations: [\"participating parties are attributable\", \"commitment and resolution are auditable\"],\n\t},\n\t\"fabric.Resource\": {\n\t\tid: \"fabric.Resource\", version: \"0.1\", description: \"A capacity or asset allocated by activities.\",\n\t\tstates: states([[\"available\", \"initial\"], [\"allocated\", \"active\"], [\"retired\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"available\", to: \"allocated\", required: true }, { from: \"allocated\", to: \"available\" }, { from: \"available\", to: \"retired\" }, { from: \"allocated\", to: \"exception\" }],\n\t\tobligations: [\"allocation is identifiable\", \"conflicting allocation is governed\"],\n\t},\n\t\"fabric.Activity\": {\n\t\tid: \"fabric.Activity\", version: \"0.1\", description: \"Work planned and performed toward an outcome.\",\n\t\tstates: states([[\"planned\", \"initial\"], [\"executing\", \"active\"], [\"waiting\", \"waiting\"], [\"completed\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"planned\", to: \"executing\", required: true }, { from: \"executing\", to: \"waiting\" }, { from: \"waiting\", to: \"executing\" }, { from: \"executing\", to: \"completed\", required: true }, { from: \"waiting\", to: \"completed\" }, { from: \"planned\", to: \"exception\" }, { from: \"executing\", to: \"exception\" }, { from: \"waiting\", to: \"exception\" }],\n\t\tobligations: [\"responsible party is attributable\", \"resource use and outcome are auditable\"],\n\t},\n\t\"fabric.Settlement\": {\n\t\tid: \"fabric.Settlement\", version: \"0.1\", description: \"Resolution of value exchange associated with an agreement.\",\n\t\tstates: states([[\"pending\", \"initial\"], [\"settled\", \"terminal\"], [\"reversed\", \"terminal\"], [\"exception\", \"exception\"]]),\n\t\ttransitions: [{ from: \"pending\", to: \"settled\", required: true }, { from: \"settled\", to: \"reversed\" }, { from: \"pending\", to: \"exception\" }],\n\t\tobligations: [\"value and currency are explicit\", \"settlement is attributable to an agreement\"],\n\t},\n};\n\nexport function archetypeSemantics(reference: ArchetypeReference): Record<string, JsonValue> {\n\treturn { [ARCHETYPE_SEMANTIC_KEY]: reference as unknown as JsonValue };\n}\n\nexport function readArchetypeReference(\n\tobjectType: ModuleManifestObjectType,\n): ArchetypeReference | undefined {\n\tconst value = objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY];\n\tif (value === undefined) return undefined;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return undefined;\n\tconst record = value as Record<string, JsonValue>;\n\tif (typeof record.id !== \"string\" || typeof record.version !== \"string\" || !record.stateMap || typeof record.stateMap !== \"object\" || Array.isArray(record.stateMap)) return undefined;\n\tif (!Object.values(record.stateMap).every((state) => typeof state === \"string\")) return undefined;\n\treturn { id: record.id as ArchetypeId, version: record.version, stateMap: record.stateMap as Record<string, string> };\n}\n\nconst transitionKey = (from: string, to: string) => `${from}->${to}`;\n\nexport function validateArchetypeConformance(\n\tmanifest: ModuleManifest,\n): ArchetypeConformanceReport[] {\n\treturn manifest.objectTypes\n\t\t.filter((objectType) => objectType.semantics?.[ARCHETYPE_SEMANTIC_KEY] !== undefined)\n\t\t.map((objectType) => validateObject(manifest, objectType));\n}\n\nfunction validateObject(\n\tmanifest: ModuleManifest,\n\tobjectType: ModuleManifestObjectType,\n): ArchetypeConformanceReport {\n\tconst findings: ConformanceFinding[] = [];\n\tconst reference = readArchetypeReference(objectType);\n\tif (!reference) {\n\t\tfindings.push({ code: \"invalid_annotation\", objectType: objectType.type, message: `Object \"${objectType.type}\" has an invalid ${ARCHETYPE_SEMANTIC_KEY} annotation.` });\n\t\treturn { conforms: false, objectType: objectType.type, findings };\n\t}\n\tconst definition = ARCHETYPES[reference.id];\n\tif (!definition) {\n\t\tfindings.push({ code: \"unknown_archetype\", objectType: objectType.type, message: `Unknown archetype \"${reference.id}\".` });\n\t\treturn { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n\t}\n\tif (reference.version !== definition.version) {\n\t\tfindings.push({ code: \"unsupported_archetype_version\", objectType: objectType.type, message: `Archetype \"${reference.id}\" supports version ${definition.version}, received ${reference.version}.` });\n\t}\n\tconst machine = (manifest.stateMachines ?? []).find((candidate) => candidate.entityType === objectType.type);\n\tif (!machine) {\n\t\tfindings.push({ code: \"missing_state_machine\", objectType: objectType.type, message: `Object \"${objectType.type}\" needs a state machine for archetype conformance.` });\n\t\treturn { conforms: false, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n\t}\n\tfor (const state of machine.states) {\n\t\tconst mapped = reference.stateMap[state.id];\n\t\tif (!mapped) {\n\t\t\tfindings.push({ code: \"unmapped_state\", objectType: objectType.type, state: state.id, message: `State \"${state.id}\" is not mapped.` });\n\t\t\tcontinue;\n\t\t}\n\t\tconst base = definition.states[mapped];\n\t\tif (!base) {\n\t\t\tfindings.push({ code: \"unknown_archetype_state\", objectType: objectType.type, state: state.id, target: mapped, message: `State \"${state.id}\" maps to unknown archetype state \"${mapped}\".` });\n\t\t} else if (base.stateClass !== state.stateClass) {\n\t\t\tfindings.push({ code: \"incompatible_state_class\", objectType: objectType.type, state: state.id, target: mapped, message: `State \"${state.id}\" (${state.stateClass}) is incompatible with \"${mapped}\" (${base.stateClass}).` });\n\t\t}\n\t}\n\tconst permitted = new Set(definition.transitions.map((transition) => transitionKey(transition.from, transition.to)));\n\tconst realized = new Set<string>();\n\tfor (const transition of machine.transitions) {\n\t\tconst from = reference.stateMap[transition.from];\n\t\tconst to = reference.stateMap[transition.to];\n\t\tif (!from || !to) continue;\n\t\tif (to === \"exception\" && !transition.hasGuard) {\n\t\t\tfindings.push({ code: \"exception_transition_unguarded\", objectType: objectType.type, state: transition.from, target: transition.to, message: `Exception transition \"${transition.from}\" -> \"${transition.to}\" must declare a governance guard.` });\n\t\t}\n\t\tif (from !== to && !permitted.has(transitionKey(from, to))) {\n\t\t\tfindings.push({ code: \"transition_not_permitted\", objectType: objectType.type, state: transition.from, target: transition.to, message: `Transition \"${transition.from}\" -> \"${transition.to}\" maps to disallowed archetype transition \"${from}\" -> \"${to}\".` });\n\t\t} else if (from !== to) {\n\t\t\trealized.add(transitionKey(from, to));\n\t\t}\n\t}\n\tfor (const required of definition.transitions.filter((transition) => transition.required)) {\n\t\tif (!realized.has(transitionKey(required.from, required.to))) {\n\t\t\tfindings.push({ code: \"required_transition_unreachable\", objectType: objectType.type, state: required.from, target: required.to, message: `Required archetype transition \"${required.from}\" -> \"${required.to}\" is not realized.` });\n\t\t}\n\t}\n\treturn { conforms: findings.length === 0, objectType: objectType.type, archetype: `${reference.id}@${reference.version}`, findings };\n}\n\nexport function assertArchetypeConformance(module: FabricModule<unknown>): void {\n\tconst failures = validateArchetypeConformance(exportModuleManifest(module)).filter((report) => !report.conforms);\n\tif (failures.length > 0) {\n\t\tthrow new Error(`Archetype conformance failed:\\n${failures.flatMap((report) => report.findings.map((finding) => `- ${report.objectType}: ${finding.message}`)).join(\"\\n\")}`);\n\t}\n}\n\nexport const archetypeConformanceAdapter: ManifestConformanceAdapter = {\n\tid: \"@fabricorg/archetypes\",\n\tevaluate: validateArchetypeConformance,\n};\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fabricorg/archetypes",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Optional cross-industry archetype vocabulary and conformance tools for Fabric module manifests.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"CHANGELOG.md"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@fabricorg/platform": "^0.11.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.10.0",
|
|
32
|
+
"tsup": "^8.5.0",
|
|
33
|
+
"typescript": "^5.7.3",
|
|
34
|
+
"vitest": "^4.1.5"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=20"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"type-check": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run"
|
|
47
|
+
}
|
|
48
|
+
}
|