@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.
- package/README.md +67 -0
- package/lib/access/conversation-directory-store.d.ts +73 -0
- package/lib/access/conversation-directory-store.d.ts.map +1 -0
- package/lib/access/conversation-directory-store.js +66 -0
- package/lib/access/conversation-directory-store.js.map +1 -0
- package/lib/access/conversation-directory.d.ts +51 -0
- package/lib/access/conversation-directory.d.ts.map +1 -0
- package/lib/access/conversation-directory.js +118 -0
- package/lib/access/conversation-directory.js.map +1 -0
- package/lib/access/manager.d.ts +47 -0
- package/lib/access/manager.d.ts.map +1 -0
- package/lib/access/manager.js +124 -0
- package/lib/access/manager.js.map +1 -0
- package/lib/access/materialize.d.ts +33 -0
- package/lib/access/materialize.d.ts.map +1 -0
- package/lib/access/materialize.js +67 -0
- package/lib/access/materialize.js.map +1 -0
- package/lib/access/owner-claim.d.ts +91 -0
- package/lib/access/owner-claim.d.ts.map +1 -0
- package/lib/access/owner-claim.js +200 -0
- package/lib/access/owner-claim.js.map +1 -0
- package/lib/access/policy-store.d.ts +55 -0
- package/lib/access/policy-store.d.ts.map +1 -0
- package/lib/access/policy-store.js +88 -0
- package/lib/access/policy-store.js.map +1 -0
- package/lib/access/validation.d.ts +29 -0
- package/lib/access/validation.d.ts.map +1 -0
- package/lib/access/validation.js +89 -0
- package/lib/access/validation.js.map +1 -0
- package/lib/auth/sanitizer.d.ts +35 -0
- package/lib/auth/sanitizer.d.ts.map +1 -0
- package/lib/auth/sanitizer.js +52 -0
- package/lib/auth/sanitizer.js.map +1 -0
- package/lib/auth/session-manager.d.ts +38 -0
- package/lib/auth/session-manager.d.ts.map +1 -0
- package/lib/auth/session-manager.js +219 -0
- package/lib/auth/session-manager.js.map +1 -0
- package/lib/config.d.ts +20 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +15 -0
- package/lib/config.js.map +1 -0
- package/lib/credentials/manager.d.ts +44 -0
- package/lib/credentials/manager.d.ts.map +1 -0
- package/lib/credentials/manager.js +24 -0
- package/lib/credentials/manager.js.map +1 -0
- package/lib/definitions/registry.d.ts +24 -0
- package/lib/definitions/registry.d.ts.map +1 -0
- package/lib/definitions/registry.js +59 -0
- package/lib/definitions/registry.js.map +1 -0
- package/lib/errors.d.ts +20 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +45 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +31 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +31 -0
- package/lib/index.js.map +1 -0
- package/lib/plugin.d.ts +20 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +81 -0
- package/lib/plugin.js.map +1 -0
- package/lib/runtime/manager.d.ts +73 -0
- package/lib/runtime/manager.d.ts.map +1 -0
- package/lib/runtime/manager.js +277 -0
- package/lib/runtime/manager.js.map +1 -0
- package/lib/runtime/mount-handle.d.ts +11 -0
- package/lib/runtime/mount-handle.d.ts.map +1 -0
- package/lib/runtime/mount-handle.js +2 -0
- package/lib/runtime/mount-handle.js.map +1 -0
- package/lib/service.d.ts +180 -0
- package/lib/service.d.ts.map +1 -0
- package/lib/service.js +432 -0
- package/lib/service.js.map +1 -0
- package/lib/types.d.ts +370 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/update-check.d.ts +128 -0
- package/lib/update-check.d.ts.map +1 -0
- package/lib/update-check.js +380 -0
- package/lib/update-check.js.map +1 -0
- package/package.json +47 -0
package/lib/service.js
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [ChannelControlService] — the universal Channel Control Plane mounted at
|
|
3
|
+
* ctx.channelControl (doc §12–§13, §33, §46).
|
|
4
|
+
*
|
|
5
|
+
* Owns the four sub-managers that later waves wire into:
|
|
6
|
+
* - definition registry (registration order)
|
|
7
|
+
* - credential access (thin wrappers over the injected structural seam)
|
|
8
|
+
* - interactive auth session lifecycle (AuthSessionManager)
|
|
9
|
+
* - runtime mount lifecycle (ChannelRuntimeManager)
|
|
10
|
+
*
|
|
11
|
+
* It is deliberately adapter-agnostic: every channel is driven through its
|
|
12
|
+
* [ChannelDefinition], never through a per-channel conditional.
|
|
13
|
+
*
|
|
14
|
+
* The credentials seam is structural ([CredentialSeam]) and injected, so this
|
|
15
|
+
* package carries no dependency on any concrete credentials implementation.
|
|
16
|
+
*/
|
|
17
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
18
|
+
import { ChannelDefinitionRegistry } from './definitions/registry.js';
|
|
19
|
+
import { CredentialManager } from './credentials/manager.js';
|
|
20
|
+
import { AuthSessionManager } from './auth/session-manager.js';
|
|
21
|
+
import { ControlError } from './errors.js';
|
|
22
|
+
import { ChannelRuntimeManager } from './runtime/manager.js';
|
|
23
|
+
import { ChannelAccessManager } from './access/manager.js';
|
|
24
|
+
import { OwnerClaimSessionManager } from './access/owner-claim.js';
|
|
25
|
+
import { ConversationDirectory, toPublicConversationIdentity } from './access/conversation-directory.js';
|
|
26
|
+
import { MemoryConversationDirectoryStore, } from './access/conversation-directory-store.js';
|
|
27
|
+
import { BundleUpdateChecker } from './update-check.js';
|
|
28
|
+
import { MemoryAccessPolicyStore, } from './access/policy-store.js';
|
|
29
|
+
const SECRET_SUFFIXES = ['secret', 'Secret', 'token', 'Token'];
|
|
30
|
+
/** Whether a config key is a secret field and must be rejected in saveConfig. */
|
|
31
|
+
function isSecretKey(name) {
|
|
32
|
+
return SECRET_SUFFIXES.some((suffix) => name.endsWith(suffix));
|
|
33
|
+
}
|
|
34
|
+
export class ChannelControlService extends Service {
|
|
35
|
+
definitions;
|
|
36
|
+
credentials;
|
|
37
|
+
auth;
|
|
38
|
+
runtime;
|
|
39
|
+
access;
|
|
40
|
+
ownerClaims;
|
|
41
|
+
/** Human identifier ↔ canonical conversation id mapping (display only). */
|
|
42
|
+
conversations;
|
|
43
|
+
/** Prompt-only bundle update check (never installs anything). */
|
|
44
|
+
updates;
|
|
45
|
+
constructor(ctx, options) {
|
|
46
|
+
super(ctx, 'channelControl');
|
|
47
|
+
this.definitions = options.registry ?? new ChannelDefinitionRegistry();
|
|
48
|
+
this.credentials = new CredentialManager(options.credentials);
|
|
49
|
+
this.auth = new AuthSessionManager({ registry: this.definitions, now: options.now });
|
|
50
|
+
this.runtime = new ChannelRuntimeManager({
|
|
51
|
+
ctx,
|
|
52
|
+
registry: this.definitions,
|
|
53
|
+
credentials: options.credentials,
|
|
54
|
+
});
|
|
55
|
+
// Access manager shares the SAME definitions registry so summarization and
|
|
56
|
+
// access reads always agree on a channel's declared descriptor.
|
|
57
|
+
const accessStore = options.accessStore ?? new MemoryAccessPolicyStore();
|
|
58
|
+
const resolveOwnerIdentity = options.resolveOwnerIdentity ?? (async (channelId, accountId) => {
|
|
59
|
+
return this.definitions.get(channelId)?.resolveOwnerIdentity?.(accountId);
|
|
60
|
+
});
|
|
61
|
+
this.access = new ChannelAccessManager({
|
|
62
|
+
registry: this.definitions,
|
|
63
|
+
store: accessStore,
|
|
64
|
+
resolveOwnerIdentity,
|
|
65
|
+
logger: this.ctx.logger('channel-control'),
|
|
66
|
+
});
|
|
67
|
+
this.ownerClaims = new OwnerClaimSessionManager({
|
|
68
|
+
registry: this.definitions,
|
|
69
|
+
store: accessStore,
|
|
70
|
+
logger: this.ctx.logger('channel-control'),
|
|
71
|
+
now: options.now,
|
|
72
|
+
});
|
|
73
|
+
this.conversations = new ConversationDirectory({
|
|
74
|
+
store: options.conversationStore ?? new MemoryConversationDirectoryStore(),
|
|
75
|
+
now: options.now,
|
|
76
|
+
logger: this.ctx.logger('channel-control'),
|
|
77
|
+
});
|
|
78
|
+
this.updates = new BundleUpdateChecker({
|
|
79
|
+
currentVersion: options.updateCheck?.currentVersion,
|
|
80
|
+
enabled: options.updateCheck?.enabled ?? true,
|
|
81
|
+
intervalHours: options.updateCheck?.intervalHours ?? 24,
|
|
82
|
+
getStorage: options.updateCheck?.storage,
|
|
83
|
+
logger: this.ctx.logger('channel-control'),
|
|
84
|
+
now: options.now,
|
|
85
|
+
});
|
|
86
|
+
// Doc §27: auto-start configured channels the moment their plugin
|
|
87
|
+
// registers the definition (channel plugins activate after this service).
|
|
88
|
+
// A registration that cannot report state or fails to start is logged by
|
|
89
|
+
// autoStartOne and never throws out of register().
|
|
90
|
+
this.definitions.onRegister((definition) => {
|
|
91
|
+
void this.runtime.autoStartOne(definition.id).catch(() => { });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// ---- convenience surface for the future v2 web API (doc §29–§33) --------
|
|
95
|
+
/** Registry + runtime + configured state merged into per-channel rows. */
|
|
96
|
+
async listChannels() {
|
|
97
|
+
const rows = [];
|
|
98
|
+
for (const definition of this.definitions.list()) {
|
|
99
|
+
rows.push(await this.summarize(definition));
|
|
100
|
+
}
|
|
101
|
+
return rows;
|
|
102
|
+
}
|
|
103
|
+
/** One merged row for a single registered channel, or a stable ChannelError. */
|
|
104
|
+
async getChannel(channelId) {
|
|
105
|
+
return this.summarize(this.definitions.require(channelId));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Enable / disable a channel (doc §22, §25). Disabling persists the intent
|
|
109
|
+
* and stops the runtime; enabling persists the intent and — when the channel
|
|
110
|
+
* is configured — starts the runtime. Returns the latest merged summary.
|
|
111
|
+
*/
|
|
112
|
+
async setEnabled(channelId, enabled) {
|
|
113
|
+
const definition = this.definitions.require(channelId);
|
|
114
|
+
if (!definition.setEnabled) {
|
|
115
|
+
throw new ControlError('ENABLE_NOT_SUPPORTED', `channel '${channelId}' does not support enable/disable`);
|
|
116
|
+
}
|
|
117
|
+
await definition.setEnabled(enabled);
|
|
118
|
+
if (!enabled) {
|
|
119
|
+
await this.runtime.stop(channelId);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
let configured = false;
|
|
123
|
+
try {
|
|
124
|
+
configured = (await definition.getConfiguredState()).configured;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
configured = false;
|
|
128
|
+
}
|
|
129
|
+
if (configured)
|
|
130
|
+
await this.runtime.start(channelId);
|
|
131
|
+
}
|
|
132
|
+
return this.getChannel(channelId);
|
|
133
|
+
}
|
|
134
|
+
/** Merge one definition's registry + runtime + configured state into a row. */
|
|
135
|
+
async summarize(definition) {
|
|
136
|
+
let configured = false;
|
|
137
|
+
try {
|
|
138
|
+
configured = (await definition.getConfiguredState()).configured;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
configured = false;
|
|
142
|
+
}
|
|
143
|
+
const enabled = definition.enabled;
|
|
144
|
+
const running = this.runtime.isRunning(definition.id);
|
|
145
|
+
// Access readiness: cheap, failure-tolerant; default to
|
|
146
|
+
// 'missing-policy' so a broken definition never breaks the collapsed row.
|
|
147
|
+
const access = await this.accessReadiness(definition.id);
|
|
148
|
+
if (running) {
|
|
149
|
+
const status = await this.runtime.status(definition.id);
|
|
150
|
+
return {
|
|
151
|
+
id: definition.id,
|
|
152
|
+
configured,
|
|
153
|
+
enabled,
|
|
154
|
+
mounted: status.mounted,
|
|
155
|
+
runtime: status.running ? 'running' : 'stopped',
|
|
156
|
+
connection: status.connection,
|
|
157
|
+
access,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
id: definition.id,
|
|
162
|
+
configured,
|
|
163
|
+
enabled,
|
|
164
|
+
mounted: false,
|
|
165
|
+
runtime: 'stopped',
|
|
166
|
+
connection: 'unknown',
|
|
167
|
+
access,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** Access readiness for a channel, guarded so failures default safely. */
|
|
171
|
+
async accessReadiness(channelId) {
|
|
172
|
+
try {
|
|
173
|
+
return (await this.access.getState(channelId, 'main')).readiness;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return 'missing-policy';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async getSetup(channelId) {
|
|
180
|
+
const definition = this.definitions.require(channelId);
|
|
181
|
+
const state = await definition.getConfiguredState();
|
|
182
|
+
return {
|
|
183
|
+
authMethods: [...definition.setup.authMethods],
|
|
184
|
+
setupUrl: definition.setup.setupUrl,
|
|
185
|
+
fields: definition.setup.fields.map((field) => {
|
|
186
|
+
const dynamic = state.fields[field.name];
|
|
187
|
+
const publicField = {
|
|
188
|
+
name: field.name,
|
|
189
|
+
kind: field.kind,
|
|
190
|
+
secret: field.secret,
|
|
191
|
+
configured: dynamic?.configured ?? field.configured,
|
|
192
|
+
writable: dynamic?.writable ?? field.writable,
|
|
193
|
+
};
|
|
194
|
+
// Surface the current value for non-secret fields only (doc §29).
|
|
195
|
+
// Secret values and the credential ref are never echoed here.
|
|
196
|
+
if (!field.secret && typeof dynamic?.value === 'string') {
|
|
197
|
+
publicField.value = dynamic.value;
|
|
198
|
+
}
|
|
199
|
+
return publicField;
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
async getConfiguredState(channelId) {
|
|
204
|
+
return this.definitions.require(channelId).getConfiguredState();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Persist a non-secret config patch for a channel. Secret fields (names
|
|
208
|
+
* ending in Secret/secret/Token/token, or declared kind:'secret' in the
|
|
209
|
+
* setup descriptor) are rejected — secret values go only through
|
|
210
|
+
* credentials.set (doc §30–§31).
|
|
211
|
+
*/
|
|
212
|
+
async saveConfig(channelId, patch) {
|
|
213
|
+
const definition = this.definitions.require(channelId);
|
|
214
|
+
const secretNames = new Set(definition.setup.fields.filter((field) => field.secret).map((field) => field.name));
|
|
215
|
+
for (const key of Object.keys(patch)) {
|
|
216
|
+
if (isSecretKey(key) || secretNames.has(key)) {
|
|
217
|
+
throw new ControlError('SECRET_FIELD_REJECTED', `config field '${key}' is a secret; save it through the credentials seam instead`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
await definition.saveConfig(patch);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Describe one credential field of a channel by its setup field name
|
|
224
|
+
* (doc §31). Resolves the field's credential ref from the setup descriptor
|
|
225
|
+
* and describes it via ctx.credentials — the value is never returned.
|
|
226
|
+
*/
|
|
227
|
+
async describeCredential(channelId, fieldName) {
|
|
228
|
+
const field = this.credentialField(channelId, fieldName);
|
|
229
|
+
if (field.ref) {
|
|
230
|
+
const described = await this.credentials.describe(field.ref);
|
|
231
|
+
return { configured: described.configured, writable: described.writable, source: described.source };
|
|
232
|
+
}
|
|
233
|
+
return { configured: false, writable: field.writable };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Save one credential field of a channel by its setup field name (doc §31).
|
|
237
|
+
* The web layer sends only { field, value }; the control plane maps the
|
|
238
|
+
* field to its credential ref and calls ctx.credentials.set. The value is
|
|
239
|
+
* never echoed back.
|
|
240
|
+
*/
|
|
241
|
+
async saveCredential(channelId, fieldName, value) {
|
|
242
|
+
const field = this.credentialField(channelId, fieldName);
|
|
243
|
+
if (!field.secret) {
|
|
244
|
+
throw new ControlError('NOT_A_SECRET_FIELD', `field '${fieldName}' is not a secret; save it through the config endpoint`);
|
|
245
|
+
}
|
|
246
|
+
if (!field.ref) {
|
|
247
|
+
throw new ControlError('CREDENTIAL_NOT_SUPPORTED', `field '${fieldName}' has no credential ref`);
|
|
248
|
+
}
|
|
249
|
+
if (!field.writable) {
|
|
250
|
+
throw new ControlError('CREDENTIAL_READONLY', `credential '${fieldName}' is read-only (not writable)`);
|
|
251
|
+
}
|
|
252
|
+
if (typeof value !== 'string') {
|
|
253
|
+
throw new ControlError('INVALID_CREDENTIAL', 'credential value must be a string');
|
|
254
|
+
}
|
|
255
|
+
// Empty value = clear/delete the stored credential (the harness credential
|
|
256
|
+
// seam rejects set(ref, '') and exposes unset for exactly this).
|
|
257
|
+
if (value === '') {
|
|
258
|
+
await this.credentials.unset(field.ref);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
await this.credentials.set(field.ref, value);
|
|
262
|
+
}
|
|
263
|
+
const described = await this.credentials.describe(field.ref);
|
|
264
|
+
return { configured: described.configured, writable: described.writable };
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Save a complete setup form and make it effective immediately. The Web
|
|
268
|
+
* sends one user action; secret and non-secret fields still cross their
|
|
269
|
+
* dedicated storage seams on the host.
|
|
270
|
+
*/
|
|
271
|
+
async applySetup(channelId, input) {
|
|
272
|
+
const definition = this.definitions.require(channelId);
|
|
273
|
+
const running = this.runtime.isRunning(channelId);
|
|
274
|
+
if (running && Object.keys(input.config).length > 0 && (!definition.snapshotConfig || !definition.restoreConfig)) {
|
|
275
|
+
throw new ControlError('CONTROL_ERROR', `channel '${channelId}' does not support transactional config updates`);
|
|
276
|
+
}
|
|
277
|
+
const configSnapshot = definition.snapshotConfig?.();
|
|
278
|
+
const credentialSnapshots = await Promise.all(Object.keys(input.credentials).map(async (fieldName) => {
|
|
279
|
+
const field = this.credentialField(channelId, fieldName);
|
|
280
|
+
if (!field.ref)
|
|
281
|
+
return undefined;
|
|
282
|
+
return { ref: field.ref, previous: await this.credentials.resolve(field.ref) };
|
|
283
|
+
}));
|
|
284
|
+
let rolledBack = false;
|
|
285
|
+
const rollback = async () => {
|
|
286
|
+
if (rolledBack)
|
|
287
|
+
return;
|
|
288
|
+
rolledBack = true;
|
|
289
|
+
if (configSnapshot !== undefined)
|
|
290
|
+
await definition.restoreConfig?.(configSnapshot);
|
|
291
|
+
for (const snapshot of credentialSnapshots) {
|
|
292
|
+
if (!snapshot)
|
|
293
|
+
continue;
|
|
294
|
+
if (snapshot.previous)
|
|
295
|
+
await this.credentials.set(snapshot.ref, snapshot.previous.value);
|
|
296
|
+
else
|
|
297
|
+
await this.credentials.unset(snapshot.ref);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
try {
|
|
301
|
+
if (Object.keys(input.config).length > 0)
|
|
302
|
+
await this.saveConfig(channelId, input.config);
|
|
303
|
+
for (const [field, value] of Object.entries(input.credentials)) {
|
|
304
|
+
await this.saveCredential(channelId, field, value);
|
|
305
|
+
}
|
|
306
|
+
const configured = await this.getConfiguredState(channelId);
|
|
307
|
+
if (!configured.configured) {
|
|
308
|
+
// Clearing a required setup value is an intentional disable. End the
|
|
309
|
+
// existing connection so its in-memory credentials cannot outlive the
|
|
310
|
+
// persisted unconfigured state.
|
|
311
|
+
if (running)
|
|
312
|
+
await this.runtime.stop(channelId);
|
|
313
|
+
return { configured: false, connection: 'unknown' };
|
|
314
|
+
}
|
|
315
|
+
if (input.reconcile === false) {
|
|
316
|
+
const status = await this.runtime.status(channelId);
|
|
317
|
+
return { configured: true, connection: status.connection };
|
|
318
|
+
}
|
|
319
|
+
if (running)
|
|
320
|
+
await this.runtime.restart(channelId, undefined, rollback);
|
|
321
|
+
else
|
|
322
|
+
await this.runtime.start(channelId);
|
|
323
|
+
const status = await this.runtime.status(channelId);
|
|
324
|
+
return { configured: true, connection: status.connection };
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
try {
|
|
328
|
+
await rollback();
|
|
329
|
+
}
|
|
330
|
+
catch (recoveryError) {
|
|
331
|
+
this.ctx.logger('channel-control').error(`[channel-control] failed to restore setup for '${channelId}'`, recoveryError);
|
|
332
|
+
}
|
|
333
|
+
throw error;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/** Resolve a setup field of a channel or raise a stable error. */
|
|
337
|
+
credentialField(channelId, fieldName) {
|
|
338
|
+
const definition = this.definitions.require(channelId);
|
|
339
|
+
const field = definition.setup.fields.find((f) => f.name === fieldName);
|
|
340
|
+
if (!field) {
|
|
341
|
+
throw new ControlError('UNKNOWN_FIELD', `channel '${channelId}' has no setup field '${fieldName}'`);
|
|
342
|
+
}
|
|
343
|
+
return field;
|
|
344
|
+
}
|
|
345
|
+
beginAuth(channelId, input) {
|
|
346
|
+
return this.auth.create(channelId, input);
|
|
347
|
+
}
|
|
348
|
+
pollAuth(sessionId) {
|
|
349
|
+
return this.auth.poll(sessionId);
|
|
350
|
+
}
|
|
351
|
+
submitAuthInput(sessionId, input) {
|
|
352
|
+
return this.auth.submit(sessionId, input);
|
|
353
|
+
}
|
|
354
|
+
cancelAuth(sessionId) {
|
|
355
|
+
return this.auth.cancel(sessionId);
|
|
356
|
+
}
|
|
357
|
+
/** Access state for a channel+account. */
|
|
358
|
+
getAccess(channelId, accountId = 'main') {
|
|
359
|
+
return this.access.getState(channelId, accountId);
|
|
360
|
+
}
|
|
361
|
+
/** Validate + persist an access policy, returning the resulting state. */
|
|
362
|
+
saveAccess(channelId, policy, accountId = 'main') {
|
|
363
|
+
return this.access.saveAccess(channelId, policy, accountId);
|
|
364
|
+
}
|
|
365
|
+
// ---- owner claim surface ----------------------------------
|
|
366
|
+
/** Begin a local owner-claim session. */
|
|
367
|
+
beginOwnerClaim(channelId, accountId = 'main') {
|
|
368
|
+
return this.ownerClaims.begin(channelId, accountId);
|
|
369
|
+
}
|
|
370
|
+
/** Read an owner-claim session (throws CLAIM_EXPIRED / CLAIM_NOT_FOUND). */
|
|
371
|
+
getOwnerClaim(channelId, claimId) {
|
|
372
|
+
return this.ownerClaims.get(channelId, claimId);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Confirm a candidate and persist the owner, then return the resulting
|
|
376
|
+
* access state for the channel+account.
|
|
377
|
+
*/
|
|
378
|
+
async confirmOwnerClaim(channelId, claimId) {
|
|
379
|
+
const session = await this.ownerClaims.confirm(channelId, claimId);
|
|
380
|
+
return this.access.getState(channelId, session.accountId);
|
|
381
|
+
}
|
|
382
|
+
/** Cancel an owner-claim session. */
|
|
383
|
+
cancelOwnerClaim(channelId, claimId) {
|
|
384
|
+
this.ownerClaims.cancel(channelId, claimId);
|
|
385
|
+
}
|
|
386
|
+
// ---- conversation identity directory (display/mapping only) --------------
|
|
387
|
+
/**
|
|
388
|
+
* Observed conversation identities for a channel+account, most recently seen
|
|
389
|
+
* first. Display/mapping metadata only — never authorization state.
|
|
390
|
+
*/
|
|
391
|
+
async listConversations(channelId, accountId = 'main') {
|
|
392
|
+
const definition = this.definitions.require(channelId);
|
|
393
|
+
const scopeRequired = definition.conversationScopeFingerprint !== undefined;
|
|
394
|
+
const scopeFingerprint = definition.conversationScopeFingerprint?.(accountId);
|
|
395
|
+
const entries = await this.conversations.list(channelId, accountId, scopeFingerprint, scopeRequired);
|
|
396
|
+
return entries.map(toPublicConversationIdentity);
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Resolve an optional human-facing identifier to its observed canonical
|
|
400
|
+
* identity. QQ's group selector uses the discovered canonical OpenID list
|
|
401
|
+
* directly and does not call this compatibility path.
|
|
402
|
+
*/
|
|
403
|
+
async findConversation(channelId, externalId, accountId = 'main') {
|
|
404
|
+
const definition = this.definitions.require(channelId);
|
|
405
|
+
const scopeRequired = definition.conversationScopeFingerprint !== undefined;
|
|
406
|
+
const scopeFingerprint = definition.conversationScopeFingerprint?.(accountId);
|
|
407
|
+
const entry = await this.conversations.resolveByExternalId(channelId, externalId, accountId, scopeFingerprint, scopeRequired);
|
|
408
|
+
return entry ? toPublicConversationIdentity(entry) : undefined;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Observe a canonical event in the conversation directory under the active
|
|
412
|
+
* provider/application scope declared by its definition. The scope is opaque
|
|
413
|
+
* metadata only; it never reaches authorization or the Web DTO.
|
|
414
|
+
*/
|
|
415
|
+
observeConversation(event) {
|
|
416
|
+
const definition = this.definitions.get(event.channel);
|
|
417
|
+
const scopeRequired = definition?.conversationScopeFingerprint !== undefined;
|
|
418
|
+
const scopeFingerprint = definition?.conversationScopeFingerprint?.(event.accountId);
|
|
419
|
+
this.conversations.observe(event, scopeFingerprint, scopeRequired);
|
|
420
|
+
}
|
|
421
|
+
// ---- bundle update check (prompt-only) ------------------------------------
|
|
422
|
+
/**
|
|
423
|
+
* Sanitized read-only update status for the web control plane and the
|
|
424
|
+
* channel `/version` command. Serves the cached snapshot immediately and
|
|
425
|
+
* refreshes in the background when stale — never blocks on the registry.
|
|
426
|
+
*/
|
|
427
|
+
getUpdateStatus() {
|
|
428
|
+
return this.updates.getStatus();
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
export { ControlError };
|
|
432
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|