@things-factory/shell 10.1.29 → 10.1.33

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.
@@ -1,5 +1,6 @@
1
1
  /*
2
- * Accent-derived slots read `--brand-<slot>` so a product can set them from its own brand.css.
2
+ * Accent-derived slots read `--brand-<slot>` so a product can set them from its own accent theme
3
+ * file, named after the product (`plant-accent.css`) - never after a shell theme file.
3
4
  * Neutral slots read `--suite-<slot>`, set by the product suite (@things-factory/operato-suite) for the
4
5
  * apps that depend on it. Bundle order does not matter for a var(); the fallback is the shell value.
5
6
  * Error, shadow and scrim stay literal on purpose - nobody above the platform owns them.
@@ -1,5 +1,6 @@
1
1
  /*
2
- * Accent-derived slots read `--brand-<slot>` so a product can set them from its own brand.css.
2
+ * Accent-derived slots read `--brand-<slot>` so a product can set them from its own accent theme
3
+ * file, named after the product (`plant-accent.css`) - never after a shell theme file.
3
4
  * Neutral slots read `--suite-<slot>`, set by the product suite (@things-factory/operato-suite) for the
4
5
  * apps that depend on it. Bundle order does not matter for a var(); the fallback is the shell value.
5
6
  * Error, shadow and scrim stay literal on purpose - nobody above the platform owns them.
@@ -12,7 +12,7 @@
12
12
  *
13
13
  * [넣는 것] 브랜드와 무관하게 항상 성립해야 하는 규칙(테마 스킴, 공통 접근성 기본값 등)
14
14
  * [넣지 않는 것] 브랜드 색값.
15
- * Products set accent colours only, as `--brand-<slot>` in their own `brand.css`. The shell
15
+ * Products set accent colours only, as `--brand-<slot>` in their own `<product>-accent.css`. The shell
16
16
  * `light.css` / `dark.css` read the 26 accent-derived md-sys slots from those variables, the 17
17
17
  * neutral slots from `--suite-<slot>` (the product suite's shared greys), and keep the last 6
18
18
  * (error, shadow, scrim) literal. See tests/md-sys-slot-owners.test.ts.
@@ -8,6 +8,8 @@ export * from './middlewares/index.js';
8
8
  export * from './bootstrap-hooks.js';
9
9
  export * from './graphql-local-client.js';
10
10
  export * from './service/index.js';
11
+ export * from './refusal/index.js';
12
+ export * from './reversibility/index.js';
11
13
  export * from './typeorm/long-text-column.js';
12
14
  export * from './typeorm/encrypt-transform.js';
13
15
  export * from './typeorm/encrypt-json-transform.js';
@@ -11,6 +11,8 @@ tslib_1.__exportStar(require("./middlewares/index.js"), exports);
11
11
  tslib_1.__exportStar(require("./bootstrap-hooks.js"), exports);
12
12
  tslib_1.__exportStar(require("./graphql-local-client.js"), exports);
13
13
  tslib_1.__exportStar(require("./service/index.js"), exports);
14
+ tslib_1.__exportStar(require("./refusal/index.js"), exports);
15
+ tslib_1.__exportStar(require("./reversibility/index.js"), exports);
14
16
  tslib_1.__exportStar(require("./typeorm/long-text-column.js"), exports);
15
17
  tslib_1.__exportStar(require("./typeorm/encrypt-transform.js"), exports);
16
18
  tslib_1.__exportStar(require("./typeorm/encrypt-json-transform.js"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,gEAAqC;AACrC,4EAAiD;AACjD,qEAA0C;AAC1C,2DAAgC;AAChC,sDAA2B;AAC3B,oEAAyC;AACzC,iEAAsC;AACtC,+DAAoC;AACpC,oEAAyC;AACzC,6DAAkC;AAElC,wEAA6C;AAC7C,yEAA8C;AAC9C,8EAAmD;AACnD,uEAA4C;AAC5C,uEAA4C","sourcesContent":["export * from './migrations/index.js'\nexport * from './initializers/naming-strategy.js'\nexport * from './initializers/database.js'\nexport * from './utils/index.js'\nexport * from './pubsub.js'\nexport * from './pubsub-log-transport.js'\nexport * from './middlewares/index.js'\nexport * from './bootstrap-hooks.js'\nexport * from './graphql-local-client.js'\nexport * from './service/index.js'\n\nexport * from './typeorm/long-text-column.js'\nexport * from './typeorm/encrypt-transform.js'\nexport * from './typeorm/encrypt-json-transform.js'\nexport * from './typeorm/json5-transform.js'\nexport * from './typeorm/round-transform.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,gEAAqC;AACrC,4EAAiD;AACjD,qEAA0C;AAC1C,2DAAgC;AAChC,sDAA2B;AAC3B,oEAAyC;AACzC,iEAAsC;AACtC,+DAAoC;AACpC,oEAAyC;AACzC,6DAAkC;AAClC,6DAAkC;AAClC,mEAAwC;AAExC,wEAA6C;AAC7C,yEAA8C;AAC9C,8EAAmD;AACnD,uEAA4C;AAC5C,uEAA4C","sourcesContent":["export * from './migrations/index.js'\nexport * from './initializers/naming-strategy.js'\nexport * from './initializers/database.js'\nexport * from './utils/index.js'\nexport * from './pubsub.js'\nexport * from './pubsub-log-transport.js'\nexport * from './middlewares/index.js'\nexport * from './bootstrap-hooks.js'\nexport * from './graphql-local-client.js'\nexport * from './service/index.js'\nexport * from './refusal/index.js'\nexport * from './reversibility/index.js'\n\nexport * from './typeorm/long-text-column.js'\nexport * from './typeorm/encrypt-transform.js'\nexport * from './typeorm/encrypt-json-transform.js'\nexport * from './typeorm/json5-transform.js'\nexport * from './typeorm/round-transform.js'\n"]}
@@ -0,0 +1 @@
1
+ export * from './refusal.js';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./refusal.js"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/refusal/index.ts"],"names":[],"mappings":";;;AAAA,uDAA4B","sourcesContent":["export * from './refusal.js'\n"]}
@@ -0,0 +1,70 @@
1
+ import { GraphQLError } from 'graphql';
2
+ import type { MiddlewareFn } from 'type-graphql';
3
+ /**
4
+ * **A refusal the server knows and names** (ADR-0054).
5
+ *
6
+ * ── Why a gate does not throw a sentence ──────────────────────────────────
7
+ * A gate that throws an English sentence puts English on a Korean screen. A screen that translates
8
+ * it is then writing the reason itself, and the gate and the screen end up with two accounts of the
9
+ * same refusal. So the gate throws a name and values, and the sentence is made where the request's
10
+ * language is known.
11
+ *
12
+ * ── What gets stored is the name ──────────────────────────────────────────
13
+ * Never write the sentence onto an event or a work row. A sentence differs per reader and the wording
14
+ * changes later; a stored one freezes that day's language. The `code` is the contract, and it travels
15
+ * unchanged to the client (ADR-0042 - no mapping table on the way out).
16
+ *
17
+ * ── Two traps ─────────────────────────────────────────────────────────────
18
+ * ① `t(key, undefined)` loses the locale and answers in English, so `params` is always passed - the
19
+ * spread below makes an object even when a refusal carries none.
20
+ * ② Never pass a **value** to `t` as a key: `:` reads as a namespace separator and cuts `urn:epc:…`
21
+ * apart. Values travel in `params` only.
22
+ *
23
+ * ── Why it lives in the shell ─────────────────────────────────────────────
24
+ * operato-plant wrote this first and operato-warehouse copied it; worklist is the third consumer as
25
+ * the work-door screens move there (ADR-0069 decision 3). Everything it needs is `graphql`,
26
+ * `type-graphql` and the request's `t`, all of which sit at or below the shell, so this is the floor
27
+ * that every consumer already stands on. The translations stay with each module: `refusalKey` names
28
+ * `error.<code>` inside the caller's own namespace, and a module that does not declare the key falls
29
+ * back to the English sentence rather than printing the key.
30
+ */
31
+ export declare class Refusal extends Error {
32
+ readonly code: string;
33
+ readonly params: RefusalParams;
34
+ /**
35
+ * @param code this refusal's name (kebab). It states **the gate's fact**; a screen does not pick its
36
+ * own sentence from this name.
37
+ * @param params the values the sentence is built from.
38
+ * @param english the sentence used when the translation key is missing. An English sentence reads
39
+ * better than the key printed raw.
40
+ */
41
+ constructor(code: string, params: RefusalParams, english: string);
42
+ }
43
+ /** Values a refusal sentence is built from. Scalars only: they travel in the GraphQL response as they are. */
44
+ export type RefusalParams = Record<string, string | number | boolean | null>;
45
+ export declare function refusalKey(code: string): string;
46
+ type Translate = (key: string, options?: Record<string, unknown>) => string;
47
+ /**
48
+ * **The one place a refusal becomes a sentence.** The resolver wrapper and the worklist callbacks both
49
+ * call this, so the two exits cannot drift apart.
50
+ *
51
+ * Apollo's own `extensions.code` gets `BAD_USER_INPUT`: a refusal is not a server error, and left empty
52
+ * Apollo would fill in `INTERNAL_SERVER_ERROR`. The name rides separately in `extensions.refusal`; its
53
+ * presence is what tells a client the server refused on purpose.
54
+ */
55
+ export declare function speakRefusal(refusal: Refusal, context: {
56
+ t?: Translate;
57
+ }): GraphQLError;
58
+ /** Rethrow a refusal as a sentence in the caller's language; anything else passes through untouched. */
59
+ export declare function rethrowSpoken(error: unknown, context: {
60
+ t?: Translate;
61
+ }): never;
62
+ /** A resolver class passes through this (`@UseMiddleware(SpeakRefusals)`). */
63
+ export declare const SpeakRefusals: MiddlewareFn<any>;
64
+ /**
65
+ * An activity callback runs inside a worklist mutation, not the module's own resolver, so
66
+ * `SpeakRefusals` never sees what it throws. Declarations wrap their callback in this: the same
67
+ * `speakRefusal`, the other exit.
68
+ */
69
+ export declare function speaksRefusals(callback: (instance: any, addendum: any, context: any) => Promise<void>): (instance: any, addendum: any, context: any) => Promise<void>;
70
+ export {};
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpeakRefusals = exports.Refusal = void 0;
4
+ exports.refusalKey = refusalKey;
5
+ exports.speakRefusal = speakRefusal;
6
+ exports.rethrowSpoken = rethrowSpoken;
7
+ exports.speaksRefusals = speaksRefusals;
8
+ const graphql_1 = require("graphql");
9
+ /**
10
+ * **A refusal the server knows and names** (ADR-0054).
11
+ *
12
+ * ── Why a gate does not throw a sentence ──────────────────────────────────
13
+ * A gate that throws an English sentence puts English on a Korean screen. A screen that translates
14
+ * it is then writing the reason itself, and the gate and the screen end up with two accounts of the
15
+ * same refusal. So the gate throws a name and values, and the sentence is made where the request's
16
+ * language is known.
17
+ *
18
+ * ── What gets stored is the name ──────────────────────────────────────────
19
+ * Never write the sentence onto an event or a work row. A sentence differs per reader and the wording
20
+ * changes later; a stored one freezes that day's language. The `code` is the contract, and it travels
21
+ * unchanged to the client (ADR-0042 - no mapping table on the way out).
22
+ *
23
+ * ── Two traps ─────────────────────────────────────────────────────────────
24
+ * ① `t(key, undefined)` loses the locale and answers in English, so `params` is always passed - the
25
+ * spread below makes an object even when a refusal carries none.
26
+ * ② Never pass a **value** to `t` as a key: `:` reads as a namespace separator and cuts `urn:epc:…`
27
+ * apart. Values travel in `params` only.
28
+ *
29
+ * ── Why it lives in the shell ─────────────────────────────────────────────
30
+ * operato-plant wrote this first and operato-warehouse copied it; worklist is the third consumer as
31
+ * the work-door screens move there (ADR-0069 decision 3). Everything it needs is `graphql`,
32
+ * `type-graphql` and the request's `t`, all of which sit at or below the shell, so this is the floor
33
+ * that every consumer already stands on. The translations stay with each module: `refusalKey` names
34
+ * `error.<code>` inside the caller's own namespace, and a module that does not declare the key falls
35
+ * back to the English sentence rather than printing the key.
36
+ */
37
+ class Refusal extends Error {
38
+ /**
39
+ * @param code this refusal's name (kebab). It states **the gate's fact**; a screen does not pick its
40
+ * own sentence from this name.
41
+ * @param params the values the sentence is built from.
42
+ * @param english the sentence used when the translation key is missing. An English sentence reads
43
+ * better than the key printed raw.
44
+ */
45
+ constructor(code, params, english) {
46
+ super(english);
47
+ this.name = 'Refusal';
48
+ this.code = code;
49
+ this.params = params;
50
+ }
51
+ }
52
+ exports.Refusal = Refusal;
53
+ function refusalKey(code) {
54
+ return `error.${code}`;
55
+ }
56
+ /**
57
+ * **The one place a refusal becomes a sentence.** The resolver wrapper and the worklist callbacks both
58
+ * call this, so the two exits cannot drift apart.
59
+ *
60
+ * Apollo's own `extensions.code` gets `BAD_USER_INPUT`: a refusal is not a server error, and left empty
61
+ * Apollo would fill in `INTERNAL_SERVER_ERROR`. The name rides separately in `extensions.refusal`; its
62
+ * presence is what tells a client the server refused on purpose.
63
+ */
64
+ function speakRefusal(refusal, context) {
65
+ const sentence = context.t
66
+ ? /* Always pass params - `undefined` here loses the locale and answers in English. */
67
+ context.t(refusalKey(refusal.code), { ...refusal.params, defaultValue: refusal.message })
68
+ : refusal.message;
69
+ return new graphql_1.GraphQLError(sentence, {
70
+ originalError: refusal,
71
+ extensions: { code: 'BAD_USER_INPUT', refusal: { code: refusal.code, params: refusal.params } }
72
+ });
73
+ }
74
+ /** Rethrow a refusal as a sentence in the caller's language; anything else passes through untouched. */
75
+ function rethrowSpoken(error, context) {
76
+ throw error instanceof Refusal ? speakRefusal(error, context) : error;
77
+ }
78
+ /** A resolver class passes through this (`@UseMiddleware(SpeakRefusals)`). */
79
+ const SpeakRefusals = async ({ context }, next) => {
80
+ try {
81
+ return await next();
82
+ }
83
+ catch (error) {
84
+ rethrowSpoken(error, context);
85
+ }
86
+ };
87
+ exports.SpeakRefusals = SpeakRefusals;
88
+ /**
89
+ * An activity callback runs inside a worklist mutation, not the module's own resolver, so
90
+ * `SpeakRefusals` never sees what it throws. Declarations wrap their callback in this: the same
91
+ * `speakRefusal`, the other exit.
92
+ */
93
+ function speaksRefusals(callback) {
94
+ return async (instance, addendum, context) => {
95
+ try {
96
+ await callback(instance, addendum, context);
97
+ }
98
+ catch (error) {
99
+ rethrowSpoken(error, context);
100
+ }
101
+ };
102
+ }
103
+ //# sourceMappingURL=refusal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refusal.js","sourceRoot":"","sources":["../../server/refusal/refusal.ts"],"names":[],"mappings":";;;AAqDA,gCAEC;AAYD,oCAUC;AAGD,sCAEC;AAgBD,wCAUC;AA5GD,qCAAsC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAa,OAAQ,SAAQ,KAAK;IAIhC;;;;;;OAMG;IACH,YAAY,IAAY,EAAE,MAAqB,EAAE,OAAe;QAC9D,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,SAAS,CAAA;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF;AAjBD,0BAiBC;AAKD,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,SAAS,IAAI,EAAE,CAAA;AACxB,CAAC;AAID;;;;;;;GAOG;AACH,SAAgB,YAAY,CAAC,OAAgB,EAAE,OAA0B;IACvE,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC;QACxB,CAAC,CAAC,oFAAoF;YACpF,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3F,CAAC,CAAC,OAAO,CAAC,OAAO,CAAA;IAEnB,OAAO,IAAI,sBAAY,CAAC,QAAQ,EAAE;QAChC,aAAa,EAAE,OAAO;QACtB,UAAU,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE;KAChG,CAAC,CAAA;AACJ,CAAC;AAED,wGAAwG;AACxG,SAAgB,aAAa,CAAC,KAAc,EAAE,OAA0B;IACtE,MAAM,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AACvE,CAAC;AAED,8EAA8E;AACvE,MAAM,aAAa,GAAsB,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE;IAC1E,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAA;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC,CAAA;AANY,QAAA,aAAa,iBAMzB;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAC5B,QAAuE;IAEvE,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { GraphQLError } from 'graphql'\nimport type { MiddlewareFn } from 'type-graphql'\n\n/**\n * **A refusal the server knows and names** (ADR-0054).\n *\n * ── Why a gate does not throw a sentence ──────────────────────────────────\n * A gate that throws an English sentence puts English on a Korean screen. A screen that translates\n * it is then writing the reason itself, and the gate and the screen end up with two accounts of the\n * same refusal. So the gate throws a name and values, and the sentence is made where the request's\n * language is known.\n *\n * ── What gets stored is the name ──────────────────────────────────────────\n * Never write the sentence onto an event or a work row. A sentence differs per reader and the wording\n * changes later; a stored one freezes that day's language. The `code` is the contract, and it travels\n * unchanged to the client (ADR-0042 - no mapping table on the way out).\n *\n * ── Two traps ─────────────────────────────────────────────────────────────\n * ① `t(key, undefined)` loses the locale and answers in English, so `params` is always passed - the\n * spread below makes an object even when a refusal carries none.\n * ② Never pass a **value** to `t` as a key: `:` reads as a namespace separator and cuts `urn:epc:…`\n * apart. Values travel in `params` only.\n *\n * ── Why it lives in the shell ─────────────────────────────────────────────\n * operato-plant wrote this first and operato-warehouse copied it; worklist is the third consumer as\n * the work-door screens move there (ADR-0069 decision 3). Everything it needs is `graphql`,\n * `type-graphql` and the request's `t`, all of which sit at or below the shell, so this is the floor\n * that every consumer already stands on. The translations stay with each module: `refusalKey` names\n * `error.<code>` inside the caller's own namespace, and a module that does not declare the key falls\n * back to the English sentence rather than printing the key.\n */\nexport class Refusal extends Error {\n readonly code: string\n readonly params: RefusalParams\n\n /**\n * @param code this refusal's name (kebab). It states **the gate's fact**; a screen does not pick its\n * own sentence from this name.\n * @param params the values the sentence is built from.\n * @param english the sentence used when the translation key is missing. An English sentence reads\n * better than the key printed raw.\n */\n constructor(code: string, params: RefusalParams, english: string) {\n super(english)\n this.name = 'Refusal'\n this.code = code\n this.params = params\n }\n}\n\n/** Values a refusal sentence is built from. Scalars only: they travel in the GraphQL response as they are. */\nexport type RefusalParams = Record<string, string | number | boolean | null>\n\nexport function refusalKey(code: string): string {\n return `error.${code}`\n}\n\ntype Translate = (key: string, options?: Record<string, unknown>) => string\n\n/**\n * **The one place a refusal becomes a sentence.** The resolver wrapper and the worklist callbacks both\n * call this, so the two exits cannot drift apart.\n *\n * Apollo's own `extensions.code` gets `BAD_USER_INPUT`: a refusal is not a server error, and left empty\n * Apollo would fill in `INTERNAL_SERVER_ERROR`. The name rides separately in `extensions.refusal`; its\n * presence is what tells a client the server refused on purpose.\n */\nexport function speakRefusal(refusal: Refusal, context: { t?: Translate }): GraphQLError {\n const sentence = context.t\n ? /* Always pass params - `undefined` here loses the locale and answers in English. */\n context.t(refusalKey(refusal.code), { ...refusal.params, defaultValue: refusal.message })\n : refusal.message\n\n return new GraphQLError(sentence, {\n originalError: refusal,\n extensions: { code: 'BAD_USER_INPUT', refusal: { code: refusal.code, params: refusal.params } }\n })\n}\n\n/** Rethrow a refusal as a sentence in the caller's language; anything else passes through untouched. */\nexport function rethrowSpoken(error: unknown, context: { t?: Translate }): never {\n throw error instanceof Refusal ? speakRefusal(error, context) : error\n}\n\n/** A resolver class passes through this (`@UseMiddleware(SpeakRefusals)`). */\nexport const SpeakRefusals: MiddlewareFn<any> = async ({ context }, next) => {\n try {\n return await next()\n } catch (error) {\n rethrowSpoken(error, context)\n }\n}\n\n/**\n * An activity callback runs inside a worklist mutation, not the module's own resolver, so\n * `SpeakRefusals` never sees what it throws. Declarations wrap their callback in this: the same\n * `speakRefusal`, the other exit.\n */\nexport function speaksRefusals(\n callback: (instance: any, addendum: any, context: any) => Promise<void>\n): (instance: any, addendum: any, context: any) => Promise<void> {\n return async (instance, addendum, context) => {\n try {\n await callback(instance, addendum, context)\n } catch (error) {\n rethrowSpoken(error, context)\n }\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export * from './reversibility.js';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./reversibility.js"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/reversibility/index.ts"],"names":[],"mappings":";;;AAAA,6DAAkC","sourcesContent":["export * from './reversibility.js'\n"]}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Whether an operation's effect can be undone (ADR-0064 decision 1).
3
+ *
4
+ * - `irreversible` the effect happens there and then, and there is no way back.
5
+ * - `compensable` it cannot be undone, but the original record stays and a new record corrects it.
6
+ * - `reversible` a paired operation returns to the same state, and no other record holds the id of a
7
+ * removed row (a row made again has a new id).
8
+ * - `unknown` not yet established. A value of its own, so the classifier never guesses a neighbour.
9
+ *
10
+ * Screens ask a destructive confirmation only for `irreversible`.
11
+ *
12
+ * ── 왜 shell 인가 (ADR-0064 보탬, 2026-09-20) ────────────────────────────────
13
+ * operato-plant 가 먼저 적었고 `@things-factory/station` 이 둘째 소비자로 서면서 올라왔다 —
14
+ * `refusal` 이 지난 길과 같다. 자리가 그 옆인 것은 같은 종류의 선언이기 때문이다: **문이 하는 일에
15
+ * 대해 서버가 아는 사실.** 소비처 넷이 이미 shell 을 들고 있다.
16
+ *
17
+ * **worklist 가 아닌 까닭.** 거기에는 이미 `Reversibility` 라는 이름이 있고 그것은 다른 타입이다
18
+ * (`{ reversible: boolean, caveat? }` — 결재 슬롯이 읽는 모양). 「승인을 되돌릴 수 있나」와 「이 문의
19
+ * 효과를 되돌릴 수 있나」는 다른 사실이고, 한 꾸러미에서 한 이름을 두고 다투게 두지 않는다.
20
+ *
21
+ * **화면은 이 상수를 import 하지 않는다.** 화면이 읽는 값은 질의로 오는 문자열이고, shell 의
22
+ * 클라이언트 진입점은 부수 효과를 들고 있어 타입 하나를 위해 지날 자리가 아니다.
23
+ */
24
+ export declare const REVERSIBILITIES: readonly ["irreversible", "compensable", "reversible", "unknown"];
25
+ export type Reversibility = (typeof REVERSIBILITIES)[number];
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REVERSIBILITIES = void 0;
4
+ /**
5
+ * Whether an operation's effect can be undone (ADR-0064 decision 1).
6
+ *
7
+ * - `irreversible` the effect happens there and then, and there is no way back.
8
+ * - `compensable` it cannot be undone, but the original record stays and a new record corrects it.
9
+ * - `reversible` a paired operation returns to the same state, and no other record holds the id of a
10
+ * removed row (a row made again has a new id).
11
+ * - `unknown` not yet established. A value of its own, so the classifier never guesses a neighbour.
12
+ *
13
+ * Screens ask a destructive confirmation only for `irreversible`.
14
+ *
15
+ * ── 왜 shell 인가 (ADR-0064 보탬, 2026-09-20) ────────────────────────────────
16
+ * operato-plant 가 먼저 적었고 `@things-factory/station` 이 둘째 소비자로 서면서 올라왔다 —
17
+ * `refusal` 이 지난 길과 같다. 자리가 그 옆인 것은 같은 종류의 선언이기 때문이다: **문이 하는 일에
18
+ * 대해 서버가 아는 사실.** 소비처 넷이 이미 shell 을 들고 있다.
19
+ *
20
+ * **worklist 가 아닌 까닭.** 거기에는 이미 `Reversibility` 라는 이름이 있고 그것은 다른 타입이다
21
+ * (`{ reversible: boolean, caveat? }` — 결재 슬롯이 읽는 모양). 「승인을 되돌릴 수 있나」와 「이 문의
22
+ * 효과를 되돌릴 수 있나」는 다른 사실이고, 한 꾸러미에서 한 이름을 두고 다투게 두지 않는다.
23
+ *
24
+ * **화면은 이 상수를 import 하지 않는다.** 화면이 읽는 값은 질의로 오는 문자열이고, shell 의
25
+ * 클라이언트 진입점은 부수 효과를 들고 있어 타입 하나를 위해 지날 자리가 아니다.
26
+ */
27
+ exports.REVERSIBILITIES = ['irreversible', 'compensable', 'reversible', 'unknown'];
28
+ //# sourceMappingURL=reversibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reversibility.js","sourceRoot":"","sources":["../../server/reversibility/reversibility.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACU,QAAA,eAAe,GAAG,CAAC,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,CAAU,CAAA","sourcesContent":["/**\n * Whether an operation's effect can be undone (ADR-0064 decision 1).\n *\n * - `irreversible` the effect happens there and then, and there is no way back.\n * - `compensable` it cannot be undone, but the original record stays and a new record corrects it.\n * - `reversible` a paired operation returns to the same state, and no other record holds the id of a\n * removed row (a row made again has a new id).\n * - `unknown` not yet established. A value of its own, so the classifier never guesses a neighbour.\n *\n * Screens ask a destructive confirmation only for `irreversible`.\n *\n * ── 왜 shell 인가 (ADR-0064 보탬, 2026-09-20) ────────────────────────────────\n * operato-plant 가 먼저 적었고 `@things-factory/station` 이 둘째 소비자로 서면서 올라왔다 —\n * `refusal` 이 지난 길과 같다. 자리가 그 옆인 것은 같은 종류의 선언이기 때문이다: **문이 하는 일에\n * 대해 서버가 아는 사실.** 소비처 넷이 이미 shell 을 들고 있다.\n *\n * **worklist 가 아닌 까닭.** 거기에는 이미 `Reversibility` 라는 이름이 있고 그것은 다른 타입이다\n * (`{ reversible: boolean, caveat? }` — 결재 슬롯이 읽는 모양). 「승인을 되돌릴 수 있나」와 「이 문의\n * 효과를 되돌릴 수 있나」는 다른 사실이고, 한 꾸러미에서 한 이름을 두고 다투게 두지 않는다.\n *\n * **화면은 이 상수를 import 하지 않는다.** 화면이 읽는 값은 질의로 오는 문자열이고, shell 의\n * 클라이언트 진입점은 부수 효과를 들고 있어 타입 하나를 위해 지날 자리가 아니다.\n */\nexport const REVERSIBILITIES = ['irreversible', 'compensable', 'reversible', 'unknown'] as const\n\nexport type Reversibility = (typeof REVERSIBILITIES)[number]\n"]}