@krischoichoi/channel-control 0.6.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.
Files changed (82) hide show
  1. package/README.md +67 -0
  2. package/lib/access/conversation-directory-store.d.ts +73 -0
  3. package/lib/access/conversation-directory-store.d.ts.map +1 -0
  4. package/lib/access/conversation-directory-store.js +66 -0
  5. package/lib/access/conversation-directory-store.js.map +1 -0
  6. package/lib/access/conversation-directory.d.ts +51 -0
  7. package/lib/access/conversation-directory.d.ts.map +1 -0
  8. package/lib/access/conversation-directory.js +118 -0
  9. package/lib/access/conversation-directory.js.map +1 -0
  10. package/lib/access/manager.d.ts +47 -0
  11. package/lib/access/manager.d.ts.map +1 -0
  12. package/lib/access/manager.js +124 -0
  13. package/lib/access/manager.js.map +1 -0
  14. package/lib/access/materialize.d.ts +33 -0
  15. package/lib/access/materialize.d.ts.map +1 -0
  16. package/lib/access/materialize.js +67 -0
  17. package/lib/access/materialize.js.map +1 -0
  18. package/lib/access/owner-claim.d.ts +91 -0
  19. package/lib/access/owner-claim.d.ts.map +1 -0
  20. package/lib/access/owner-claim.js +200 -0
  21. package/lib/access/owner-claim.js.map +1 -0
  22. package/lib/access/policy-store.d.ts +55 -0
  23. package/lib/access/policy-store.d.ts.map +1 -0
  24. package/lib/access/policy-store.js +88 -0
  25. package/lib/access/policy-store.js.map +1 -0
  26. package/lib/access/validation.d.ts +29 -0
  27. package/lib/access/validation.d.ts.map +1 -0
  28. package/lib/access/validation.js +89 -0
  29. package/lib/access/validation.js.map +1 -0
  30. package/lib/auth/sanitizer.d.ts +35 -0
  31. package/lib/auth/sanitizer.d.ts.map +1 -0
  32. package/lib/auth/sanitizer.js +52 -0
  33. package/lib/auth/sanitizer.js.map +1 -0
  34. package/lib/auth/session-manager.d.ts +38 -0
  35. package/lib/auth/session-manager.d.ts.map +1 -0
  36. package/lib/auth/session-manager.js +219 -0
  37. package/lib/auth/session-manager.js.map +1 -0
  38. package/lib/config.d.ts +20 -0
  39. package/lib/config.d.ts.map +1 -0
  40. package/lib/config.js +15 -0
  41. package/lib/config.js.map +1 -0
  42. package/lib/credentials/manager.d.ts +44 -0
  43. package/lib/credentials/manager.d.ts.map +1 -0
  44. package/lib/credentials/manager.js +24 -0
  45. package/lib/credentials/manager.js.map +1 -0
  46. package/lib/definitions/registry.d.ts +24 -0
  47. package/lib/definitions/registry.d.ts.map +1 -0
  48. package/lib/definitions/registry.js +59 -0
  49. package/lib/definitions/registry.js.map +1 -0
  50. package/lib/errors.d.ts +20 -0
  51. package/lib/errors.d.ts.map +1 -0
  52. package/lib/errors.js +45 -0
  53. package/lib/errors.js.map +1 -0
  54. package/lib/index.d.ts +31 -0
  55. package/lib/index.d.ts.map +1 -0
  56. package/lib/index.js +31 -0
  57. package/lib/index.js.map +1 -0
  58. package/lib/plugin.d.ts +20 -0
  59. package/lib/plugin.d.ts.map +1 -0
  60. package/lib/plugin.js +81 -0
  61. package/lib/plugin.js.map +1 -0
  62. package/lib/runtime/manager.d.ts +73 -0
  63. package/lib/runtime/manager.d.ts.map +1 -0
  64. package/lib/runtime/manager.js +277 -0
  65. package/lib/runtime/manager.js.map +1 -0
  66. package/lib/runtime/mount-handle.d.ts +11 -0
  67. package/lib/runtime/mount-handle.d.ts.map +1 -0
  68. package/lib/runtime/mount-handle.js +2 -0
  69. package/lib/runtime/mount-handle.js.map +1 -0
  70. package/lib/service.d.ts +180 -0
  71. package/lib/service.d.ts.map +1 -0
  72. package/lib/service.js +432 -0
  73. package/lib/service.js.map +1 -0
  74. package/lib/types.d.ts +370 -0
  75. package/lib/types.d.ts.map +1 -0
  76. package/lib/types.js +2 -0
  77. package/lib/types.js.map +1 -0
  78. package/lib/update-check.d.ts +128 -0
  79. package/lib/update-check.d.ts.map +1 -0
  80. package/lib/update-check.js +380 -0
  81. package/lib/update-check.js.map +1 -0
  82. package/package.json +47 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * [ChannelDefinitionRegistry] — registration-order store of ChannelDefinitions.
3
+ *
4
+ * Each channel plugin registers exactly one definition at activation time; the
5
+ * control plane drives setup/authorization/runtime purely through these
6
+ * definitions (doc §14). Iteration is in registration order.
7
+ */
8
+ import { ChannelDuplicateError, ChannelError } from '@krischoichoi/channel-core';
9
+ export class ChannelDefinitionRegistry {
10
+ definitions = new Map();
11
+ listeners = new Set();
12
+ /**
13
+ * Subscribe to definition registrations. The returned disposer removes the
14
+ * listener. Fired synchronously after a successful register() — the control
15
+ * plane uses this to auto-start configured channels the moment their plugin
16
+ * registers the definition (doc §27), since channel plugins activate AFTER
17
+ * the channel-control plugin itself.
18
+ */
19
+ onRegister(listener) {
20
+ this.listeners.add(listener);
21
+ return () => {
22
+ this.listeners.delete(listener);
23
+ };
24
+ }
25
+ /** Register a definition; throws ChannelDuplicateError on duplicate id. */
26
+ register(definition) {
27
+ const { id } = definition;
28
+ if (this.definitions.has(id)) {
29
+ throw new ChannelDuplicateError(`channel definition '${id}' is already registered`);
30
+ }
31
+ this.definitions.set(id, definition);
32
+ for (const listener of this.listeners) {
33
+ listener(definition);
34
+ }
35
+ }
36
+ get(id) {
37
+ return this.definitions.get(id);
38
+ }
39
+ /** Require a definition, or raise a stable ChannelError. */
40
+ require(id) {
41
+ const definition = this.definitions.get(id);
42
+ if (!definition) {
43
+ throw new ChannelError('CHANNEL_ERROR', `channel definition '${id}' is not registered`);
44
+ }
45
+ return definition;
46
+ }
47
+ has(id) {
48
+ return this.definitions.has(id);
49
+ }
50
+ /** List definitions in registration order. */
51
+ list() {
52
+ return [...this.definitions.values()];
53
+ }
54
+ /** Remove a definition; returns whether it existed. */
55
+ unregister(id) {
56
+ return this.definitions.delete(id);
57
+ }
58
+ }
59
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/definitions/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAGjF,MAAM,OAAO,yBAAyB;IACnB,WAAW,GAAG,IAAI,GAAG,EAA6B,CAAC;IACnD,SAAS,GAAG,IAAI,GAAG,EAA2C,CAAC;IAEhF;;;;;;OAMG;IACH,UAAU,CAAC,QAAiD;QAC1D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,UAA6B;QACpC,MAAM,EAAE,EAAE,EAAE,GAAG,UAAU,CAAC;QAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,qBAAqB,CAC7B,uBAAuB,EAAE,yBAAyB,CACnD,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACrC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,4DAA4D;IAC5D,OAAO,CAAC,EAAU;QAChB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,YAAY,CACpB,eAAe,EACf,uBAAuB,EAAE,qBAAqB,CAC/C,CAAC;QACJ,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,8CAA8C;IAC9C,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,uDAAuD;IACvD,UAAU,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Control-plane error hierarchy with stable machine-readable codes.
3
+ *
4
+ * Channel-level errors reuse [ChannelError] from @krischoichoi/channel-core (e.g.
5
+ * duplicate definition ids). The control plane additionally defines codes for
6
+ * its own security/session concerns (auth not supported, unknown/cancelled/
7
+ * expired sessions, rejected secret fields) that are NOT part of the core's
8
+ * fixed [ChannelErrorCode] union, so they live here without touching core.
9
+ */
10
+ export type ControlErrorCode = 'CONTROL_ERROR' | 'CONTROL_DEFINITION_NOT_FOUND' | 'AUTH_NOT_SUPPORTED' | 'AUTH_SESSION_NOT_FOUND' | 'AUTH_SESSION_CANCELLED' | 'AUTH_SESSION_EXPIRED' | 'AUTH_NOT_READY' | 'ENABLE_NOT_SUPPORTED' | 'SECRET_FIELD_REJECTED' | 'NOT_A_SECRET_FIELD' | 'CREDENTIAL_NOT_SUPPORTED' | 'CREDENTIAL_READONLY' | 'INVALID_CREDENTIAL' | 'UNKNOWN_FIELD' | 'INVALID_ACCESS_POLICY' | 'CLAIM_NOT_FOUND' | 'CLAIM_EXPIRED' | 'CLAIM_CANCELLED' | 'CLAIM_NOT_SUPPORTED' | 'CLAIM_INVALID';
11
+ /** Base control-plane error. */
12
+ export declare class ControlError extends Error {
13
+ readonly code: ControlErrorCode;
14
+ constructor(code?: ControlErrorCode, message?: string, options?: ErrorOptions);
15
+ }
16
+ /** Whether a value is a control error with the given code. */
17
+ export declare function isControlError(error: unknown, code?: ControlErrorCode): error is ControlError;
18
+ /** Normalize an unknown thrown value into a ControlError with a stable code. */
19
+ export declare function toControlError(error: unknown, code: ControlErrorCode, fallback?: string): ControlError;
20
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,8BAA8B,GAC9B,oBAAoB,GACpB,wBAAwB,GACxB,wBAAwB,GACxB,sBAAsB,GACtB,gBAAgB,GAChB,sBAAsB,GACtB,uBAAuB,GACvB,oBAAoB,GACpB,0BAA0B,GAC1B,qBAAqB,GACrB,oBAAoB,GACpB,eAAe,GACf,uBAAuB,GACvB,iBAAiB,GACjB,eAAe,GACf,iBAAiB,GACjB,qBAAqB,GACrB,eAAe,CAAC;AAyBpB,gCAAgC;AAChC,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;gBAEpB,IAAI,GAAE,gBAAkC,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAK/F;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,KAAK,IAAI,YAAY,CAG7F;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,gBAAgB,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB,YAAY,CAId"}
package/lib/errors.js ADDED
@@ -0,0 +1,45 @@
1
+ const MESSAGES = {
2
+ CONTROL_ERROR: 'channel control error',
3
+ CONTROL_DEFINITION_NOT_FOUND: 'channel definition is not registered',
4
+ AUTH_NOT_SUPPORTED: 'channel does not support interactive authorization',
5
+ AUTH_SESSION_NOT_FOUND: 'auth session not found',
6
+ AUTH_SESSION_CANCELLED: 'auth session was cancelled',
7
+ AUTH_SESSION_EXPIRED: 'auth session has expired',
8
+ AUTH_NOT_READY: 'channel is not mounted; start it before beginning auth',
9
+ ENABLE_NOT_SUPPORTED: 'channel does not support enable/disable',
10
+ SECRET_FIELD_REJECTED: 'secret fields must be saved through the credentials seam',
11
+ NOT_A_SECRET_FIELD: 'field is not a secret; save it through the config endpoint',
12
+ CREDENTIAL_NOT_SUPPORTED: 'field has no credential ref',
13
+ CREDENTIAL_READONLY: 'credential is read-only (not writable)',
14
+ INVALID_CREDENTIAL: 'credential value must be a string (empty string clears it)',
15
+ UNKNOWN_FIELD: 'channel has no such setup field',
16
+ INVALID_ACCESS_POLICY: 'access policy is invalid for this channel',
17
+ CLAIM_NOT_FOUND: 'owner claim not found',
18
+ CLAIM_EXPIRED: 'owner claim has expired',
19
+ CLAIM_CANCELLED: 'owner claim was cancelled',
20
+ CLAIM_NOT_SUPPORTED: 'channel does not support owner claim',
21
+ CLAIM_INVALID: 'owner claim is in an invalid state for this operation',
22
+ };
23
+ /** Base control-plane error. */
24
+ export class ControlError extends Error {
25
+ code;
26
+ constructor(code = 'CONTROL_ERROR', message, options) {
27
+ super(message ?? MESSAGES[code], options);
28
+ this.name = 'ControlError';
29
+ this.code = code;
30
+ }
31
+ }
32
+ /** Whether a value is a control error with the given code. */
33
+ export function isControlError(error, code) {
34
+ if (!(error instanceof ControlError))
35
+ return false;
36
+ return code === undefined || error.code === code;
37
+ }
38
+ /** Normalize an unknown thrown value into a ControlError with a stable code. */
39
+ export function toControlError(error, code, fallback) {
40
+ if (error instanceof ControlError)
41
+ return error;
42
+ const message = error instanceof Error ? error.message : String(error);
43
+ return new ControlError(code, fallback ?? message);
44
+ }
45
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AA+BA,MAAM,QAAQ,GAAqC;IACjD,aAAa,EAAE,uBAAuB;IACtC,4BAA4B,EAAE,sCAAsC;IACpE,kBAAkB,EAAE,oDAAoD;IACxE,sBAAsB,EAAE,wBAAwB;IAChD,sBAAsB,EAAE,4BAA4B;IACpD,oBAAoB,EAAE,0BAA0B;IAChD,cAAc,EAAE,wDAAwD;IACxE,oBAAoB,EAAE,yCAAyC;IAC/D,qBAAqB,EAAE,0DAA0D;IACjF,kBAAkB,EAAE,4DAA4D;IAChF,wBAAwB,EAAE,6BAA6B;IACvD,mBAAmB,EAAE,wCAAwC;IAC7D,kBAAkB,EAAE,4DAA4D;IAChF,aAAa,EAAE,iCAAiC;IAChD,qBAAqB,EAAE,2CAA2C;IAClE,eAAe,EAAE,uBAAuB;IACxC,aAAa,EAAE,yBAAyB;IACxC,eAAe,EAAE,2BAA2B;IAC5C,mBAAmB,EAAE,sCAAsC;IAC3D,aAAa,EAAE,uDAAuD;CACvE,CAAC;AAEF,gCAAgC;AAChC,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAmB;IAEhC,YAAY,OAAyB,eAAe,EAAE,OAAgB,EAAE,OAAsB;QAC5F,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,IAAuB;IACpE,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;AACnD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAC5B,KAAc,EACd,IAAsB,EACtB,QAAiB;IAEjB,IAAI,KAAK,YAAY,YAAY;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,IAAI,YAAY,CAAC,IAAI,EAAE,QAAQ,IAAI,OAAO,CAAC,CAAC;AACrD,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @krischoichoi/channel-control — universal Channel Control Plane.
3
+ *
4
+ * Exports the control-plane types (doc §14–§18), the sub-managers
5
+ * (definition registry, credential manager, auth session manager, runtime
6
+ * manager), the [ChannelControlService] (Cordis Service at ctx.channelControl)
7
+ * and the control-plane error hierarchy.
8
+ *
9
+ * This package is adapter-agnostic: it never imports channel-weixin/qq/
10
+ * dingtalk/lark/web. Platform differences are sealed behind ChannelDefinition.
11
+ *
12
+ * The Cordis plugin entry lives in ./plugin.ts (package export "./plugin").
13
+ */
14
+ export * from './types.js';
15
+ export * from './errors.js';
16
+ export * from './config.js';
17
+ export * from './definitions/registry.js';
18
+ export * from './credentials/manager.js';
19
+ export * from './auth/sanitizer.js';
20
+ export * from './auth/session-manager.js';
21
+ export * from './runtime/manager.js';
22
+ export * from './runtime/mount-handle.js';
23
+ export * from './access/policy-store.js';
24
+ export * from './access/conversation-directory.js';
25
+ export * from './access/conversation-directory-store.js';
26
+ export * from './access/validation.js';
27
+ export * from './access/materialize.js';
28
+ export * from './access/manager.js';
29
+ export * from './update-check.js';
30
+ export * from './service.js';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @krischoichoi/channel-control — universal Channel Control Plane.
3
+ *
4
+ * Exports the control-plane types (doc §14–§18), the sub-managers
5
+ * (definition registry, credential manager, auth session manager, runtime
6
+ * manager), the [ChannelControlService] (Cordis Service at ctx.channelControl)
7
+ * and the control-plane error hierarchy.
8
+ *
9
+ * This package is adapter-agnostic: it never imports channel-weixin/qq/
10
+ * dingtalk/lark/web. Platform differences are sealed behind ChannelDefinition.
11
+ *
12
+ * The Cordis plugin entry lives in ./plugin.ts (package export "./plugin").
13
+ */
14
+ export * from './types.js';
15
+ export * from './errors.js';
16
+ export * from './config.js';
17
+ export * from './definitions/registry.js';
18
+ export * from './credentials/manager.js';
19
+ export * from './auth/sanitizer.js';
20
+ export * from './auth/session-manager.js';
21
+ export * from './runtime/manager.js';
22
+ export * from './runtime/mount-handle.js';
23
+ export * from './access/policy-store.js';
24
+ export * from './access/conversation-directory.js';
25
+ export * from './access/conversation-directory-store.js';
26
+ export * from './access/validation.js';
27
+ export * from './access/materialize.js';
28
+ export * from './access/manager.js';
29
+ export * from './update-check.js';
30
+ export * from './service.js';
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oCAAoC,CAAC;AACnD,cAAc,0CAA0C,CAAC;AACzD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Cordis plugin entry for @krischoichoi/channel-control (doc §12, §46).
3
+ *
4
+ * Instantiates the ChannelControlService, then auto-starts every configured
5
+ * channel (headless support, doc §25/§27). autoStartAll is guarded so a single
6
+ * misconfigured/broken channel can never crash profile activation. On fiber
7
+ * unload the plugin stops and disposes every runtime mount.
8
+ *
9
+ * The access manager is wired over the shared, durable channel-domain storage
10
+ * (`ctx.channels.resources.storage`) so policies written here and read by the
11
+ * harness resolver share one KV namespace. Owner identity resolution
12
+ * delegates to each registered definition's optional `resolveOwnerIdentity`.
13
+ */
14
+ import { type Context } from '@deepseek-ai/cordis';
15
+ import { Config, type Config as ChannelControlConfig } from './config.js';
16
+ export declare const name = "channel-control";
17
+ export declare const inject: string[];
18
+ export { Config };
19
+ export declare function apply(ctx: Context, config: ChannelControlConfig): void;
20
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAMnD,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,IAAI,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE1E,eAAO,MAAM,IAAI,oBAAoB,CAAC;AACtC,eAAO,MAAM,MAAM,EAAE,MAAM,EAAgC,CAAC;AAE5D,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAyEtE"}
package/lib/plugin.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Cordis plugin entry for @krischoichoi/channel-control (doc §12, §46).
3
+ *
4
+ * Instantiates the ChannelControlService, then auto-starts every configured
5
+ * channel (headless support, doc §25/§27). autoStartAll is guarded so a single
6
+ * misconfigured/broken channel can never crash profile activation. On fiber
7
+ * unload the plugin stops and disposes every runtime mount.
8
+ *
9
+ * The access manager is wired over the shared, durable channel-domain storage
10
+ * (`ctx.channels.resources.storage`) so policies written here and read by the
11
+ * harness resolver share one KV namespace. Owner identity resolution
12
+ * delegates to each registered definition's optional `resolveOwnerIdentity`.
13
+ */
14
+ import {} from '@deepseek-ai/cordis';
15
+ import { ChannelControlService } from './service.js';
16
+ import { ChannelStorageAccessPolicyStore } from './access/policy-store.js';
17
+ import { ChannelStorageConversationDirectoryStore } from './access/conversation-directory-store.js';
18
+ import { Config } from './config.js';
19
+ export const name = 'channel-control';
20
+ export const inject = ['channels', 'credentials'];
21
+ export { Config };
22
+ export function apply(ctx, config) {
23
+ const credentials = ctx.credentials;
24
+ const channels = ctx.channels;
25
+ // The resolver closure references `service`; annotate it explicitly so the
26
+ // self-reference resolves without circular-inference.
27
+ let service;
28
+ service = new ChannelControlService(ctx, {
29
+ credentials,
30
+ // Durable policy store over the same ChannelStorage the harness resolver reads.
31
+ accessStore: new ChannelStorageAccessPolicyStore(() => channels.resources.storage),
32
+ // Durable conversation-identity directory over the same shared storage.
33
+ conversationStore: new ChannelStorageConversationDirectoryStore(() => channels.resources.storage),
34
+ // Owner identity resolution delegates to the registered definition's hook.
35
+ resolveOwnerIdentity: async (channelId, accountId) => service.definitions.get(channelId)?.resolveOwnerIdentity?.(accountId),
36
+ // Prompt-only bundle update check over the same durable channel storage.
37
+ updateCheck: {
38
+ enabled: config.updateCheck.enabled,
39
+ intervalHours: config.updateCheck.intervalHours,
40
+ storage: () => channels.resources.storage,
41
+ },
42
+ });
43
+ // Fire-and-forget startup check (never blocks activation; offline-tolerant;
44
+ // prompt-only — it never installs anything).
45
+ void service.updates.trigger();
46
+ // Headless auto-start: definitions registered BEFORE this plugin activates
47
+ // are swept here; definitions registered afterwards (channel plugins
48
+ // activate after channel-control) are auto-started by the service's
49
+ // onRegister hook (doc §27). Unconfigured channels are skipped silently and
50
+ // a failed start never crashes plugin activation.
51
+ void (async () => {
52
+ try {
53
+ await service.runtime.autoStartAll();
54
+ }
55
+ catch (error) {
56
+ ctx.logger('channel-control').error('[channel-control] autoStartAll failed during activation', error);
57
+ }
58
+ })();
59
+ // On fiber unload, stop and dispose every mounted runtime adapter.
60
+ ctx.effect(() => {
61
+ return () => service.runtime.stopAll().catch(() => { });
62
+ });
63
+ // Event listeners for the owner-claim session manager and the conversation
64
+ // identity directory. Neither observe() ever throws intentionally (both catch
65
+ // and log internally), but wrap them anyway so a failure can never propagate
66
+ // back to the adapter inbound loop (which would treat the whole platform
67
+ // message as failed). The disposer is returned through ctx.effect teardown.
68
+ ctx.effect(() => {
69
+ const off = channels.on((event) => {
70
+ try {
71
+ service.ownerClaims.observe(event);
72
+ service.observeConversation(event);
73
+ }
74
+ catch (error) {
75
+ ctx.logger('channel-control').warn('[channel-control] channel event observe failed', error);
76
+ }
77
+ });
78
+ return off;
79
+ });
80
+ }
81
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * [ChannelRuntimeManager] — start/stop/restart/status for mounted channel
3
+ * adapters (doc §21–§23, §25, §60; M2 Task 3 / M3 Task 6).
4
+ *
5
+ * Each mount lives in a Map keyed by `channelId:accountId` (default
6
+ * account 'main'). Starting an already-mounted key disposes the old mount
7
+ * first (restart semantics). The underlying mount is transactional — mirroring
8
+ * channel-core's mountChannelAdapter: register → start → rollback on failure
9
+ * (abort + stop + unregister + rethrow). Because the runtime must AWAIT
10
+ * startup and capture start errors (the opaque core handle does not expose a
11
+ * settle promise), the mount here drives the SAME Cordis effect directly and
12
+ * exposes a `ChannelMountHandle`-shaped disposer, so a failed start never
13
+ * leaves a residual registry entry and surfaces lastError via status().
14
+ *
15
+ * autoStartAll() mounts every registered definition whose autoStart is not
16
+ * false and whose dynamic configured state is configured; unconfigured
17
+ * channels are skipped silently (doc §25/§27) and a failing definition is
18
+ * logged, never allowed to crash plugin activation.
19
+ */
20
+ import type { Context } from '@deepseek-ai/cordis';
21
+ import type { ChannelAdapter } from '@krischoichoi/channel-core';
22
+ import { ChannelDefinitionRegistry } from '../definitions/registry.js';
23
+ import type { CredentialSeam } from '../credentials/manager.js';
24
+ import type { ChannelRuntimeStatus } from '../types.js';
25
+ export interface ChannelRuntimeManagerOptions {
26
+ ctx: Context;
27
+ registry: ChannelDefinitionRegistry;
28
+ credentials: CredentialSeam;
29
+ }
30
+ export declare class ChannelRuntimeManager {
31
+ private readonly mounts;
32
+ private readonly errors;
33
+ private readonly ctx;
34
+ private readonly registry;
35
+ private readonly credentials;
36
+ constructor(options: ChannelRuntimeManagerOptions);
37
+ key(channelId: string, accountId?: string): string;
38
+ start(channelId: string, accountId?: string): Promise<void>;
39
+ stop(channelId: string, accountId?: string): Promise<void>;
40
+ restart(channelId: string, accountId?: string, rollback?: () => Promise<void> | void): Promise<void>;
41
+ status(channelId: string, accountId?: string): Promise<ChannelRuntimeStatus>;
42
+ isRunning(channelId: string, accountId?: string): boolean;
43
+ /**
44
+ * The currently mounted adapter for a channel (doc §43: the Weixin
45
+ * definition delegates beginAuth/pollAuth/submitAuthInput to the mounted
46
+ * adapter so the M1 auth flow itself is unchanged). Returns undefined when
47
+ * not mounted.
48
+ */
49
+ adapter(channelId: string, accountId?: string): ChannelAdapter | undefined;
50
+ /**
51
+ * Auto-start ONE definition when it is registered (doc §27). Skips
52
+ * silently when autoStart is false or the channel is not configured; a
53
+ * failing start is logged and never thrown (registration must not crash
54
+ * the profile). Returns true when mounted.
55
+ */
56
+ autoStartOne(channelId: string): Promise<boolean>;
57
+ /**
58
+ * Mount every enabled+configured registered definition (doc §25, §27).
59
+ * Unconfigured channels are skipped silently. A failing start is logged and
60
+ * never propagates, so an unconfigured/broken channel cannot crash the
61
+ * profile. Returns { started, skipped } counts.
62
+ */
63
+ autoStartAll(): Promise<{
64
+ started: number;
65
+ skipped: number;
66
+ failed: number;
67
+ }>;
68
+ /** Dispose and forget every mounted adapter. */
69
+ stopAll(): Promise<void>;
70
+ private mountTransactional;
71
+ private mount;
72
+ }
73
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/runtime/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,4BAA4B,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxD,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,yBAAyB,CAAC;IACpC,WAAW,EAAE,cAAc,CAAC;CAC7B;AAUD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAiB;gBAEjC,OAAO,EAAE,4BAA4B;IAMjD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAI5C,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3D,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC;IA2CV,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA4ClF,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO;IAIzD;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI1E;;;;;OAKG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBvD;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAyCnF,gDAAgD;IAC1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,OAAO,CAAC,kBAAkB;YAgDZ,KAAK;CAUpB"}