@kubun/plugin-connector 0.14.1 → 0.14.2

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/lib/manager.js CHANGED
@@ -3,12 +3,22 @@ export class ConnectorManager {
3
3
  #registry;
4
4
  #logger;
5
5
  #activeGraphs = new Map();
6
- #events = new EventEmitter();
7
- #syncEvents = new EventEmitter();
6
+ #events;
7
+ #syncEvents;
8
+ #lifecycleEvents;
8
9
  #defaults;
9
10
  constructor(params){
10
11
  this.#registry = params.registry;
11
12
  this.#logger = params.logger;
13
+ this.#events = new EventEmitter({
14
+ logger: params.logger
15
+ });
16
+ this.#syncEvents = new EventEmitter({
17
+ logger: params.logger
18
+ });
19
+ this.#lifecycleEvents = new EventEmitter({
20
+ logger: params.logger
21
+ });
12
22
  this.#defaults = {
13
23
  boundary: params.defaults?.boundary ?? {
14
24
  maxAge: 'P90D'
@@ -35,7 +45,7 @@ export class ConnectorManager {
35
45
  name,
36
46
  graphID
37
47
  });
38
- this.#events.emit('connector:activated', {
48
+ this.#events.fire('connector:activated', {
39
49
  connectorName: name,
40
50
  graphID
41
51
  });
@@ -54,7 +64,7 @@ export class ConnectorManager {
54
64
  this.#logger.info('Connector {name} deactivated', {
55
65
  name
56
66
  });
57
- this.#events.emit('connector:deactivated', {
67
+ this.#events.fire('connector:deactivated', {
58
68
  connectorName: name
59
69
  });
60
70
  }
@@ -77,11 +87,36 @@ export class ConnectorManager {
77
87
  onConnectorDeactivated(callback) {
78
88
  return this.#events.on('connector:deactivated', callback);
79
89
  }
90
+ /**
91
+ * Listen-only view of the typed event channel. Consumers subscribe here (e.g.
92
+ * `events.on('connector:authenticated', …)`); the emit side stays private to
93
+ * the manager, so the returned surface carries no `fire`/`emit`.
94
+ */ get events() {
95
+ return this.#events;
96
+ }
97
+ /** Listen-only view of the merged lifecycle channel carrying every tagged event. */ get lifecycleEvents() {
98
+ return this.#lifecycleEvents;
99
+ }
100
+ /**
101
+ * Emit a lifecycle event to both the typed per-event channel and the merged
102
+ * channel. The two `fire` calls are independent and failure-isolated: a
103
+ * throwing listener on either channel is reported via the logger and cannot
104
+ * reject the caller or block the other channel.
105
+ */ emitLifecycle(type, payload) {
106
+ this.#emitLifecycle(type, payload);
107
+ }
108
+ #emitLifecycle(type, payload) {
109
+ this.#events.fire(type, payload);
110
+ this.#lifecycleEvents.fire('lifecycle', {
111
+ type,
112
+ ...payload
113
+ });
114
+ }
80
115
  get syncEvents() {
81
116
  return this.#syncEvents;
82
117
  }
83
- async emitSyncEvent(event) {
84
- await this.#syncEvents.emit('sync', event);
118
+ emitSyncEvent(event) {
119
+ this.#syncEvents.fire('sync', event);
85
120
  }
86
121
  onSyncEvent(callback) {
87
122
  return this.#syncEvents.on('sync', callback);
package/lib/oauth.d.ts CHANGED
@@ -4,6 +4,10 @@ import type { Runtime } from '@sozai/runtime';
4
4
  import type { ConnectorAPI, CredentialAPI } from './api.js';
5
5
  import type { ConnectorRegistry } from './registry.js';
6
6
  import type { CompleteConnectorAuthInput, CompleteConnectorAuthOutput, StartConnectorAuthInput, StartConnectorAuthOutput } from './schema.js';
7
+ export type CompleteAuthResult = {
8
+ output: CompleteConnectorAuthOutput;
9
+ ownerDID: string;
10
+ };
7
11
  export type OAuthServiceParams = {
8
12
  runtime: Runtime;
9
13
  providers: Array<OAuthProviderDefinition>;
@@ -16,5 +20,5 @@ export declare class OAuthService {
16
20
  #private;
17
21
  constructor(params: OAuthServiceParams);
18
22
  startAuth(args: StartConnectorAuthInput, ownerDID: string, connectorAPI?: ConnectorAPI, preflightMethods?: MethodRegistry): Promise<StartConnectorAuthOutput>;
19
- completeAuth(args: CompleteConnectorAuthInput, credentialProvider?: CredentialProvider, connectorAPI?: ConnectorAPI): Promise<CompleteConnectorAuthOutput>;
23
+ completeAuth(args: CompleteConnectorAuthInput, credentialProvider?: CredentialProvider, connectorAPI?: ConnectorAPI): Promise<CompleteAuthResult>;
20
24
  }
package/lib/oauth.js CHANGED
@@ -167,8 +167,11 @@ export class OAuthService {
167
167
  controllerWrappableDID: pending.controllerWrappableDID ?? undefined
168
168
  });
169
169
  return {
170
- providerName: args.provider,
171
- scopes
170
+ output: {
171
+ providerName: args.provider,
172
+ scopes
173
+ },
174
+ ownerDID: pending.ownerDID
172
175
  };
173
176
  }
174
177
  }
@@ -0,0 +1,4 @@
1
+ export declare function periodicSyncSubject(connector: string, ownerDID: string): {
2
+ owner: string;
3
+ subjectKey: string;
4
+ };
@@ -0,0 +1,12 @@
1
+ import { normalizeDID } from '@kokuin/token';
2
+ // The adaptive schedule and the manual-sync singleton share one subject so a
3
+ // scheduled run and a manual trigger interlock. Both fold the owner to its short
4
+ // form first: credential rows and sync-state rows are keyed on the normalized
5
+ // DID, and a viewer can arrive long-form (a mutation's `iss`).
6
+ export function periodicSyncSubject(connector, ownerDID) {
7
+ const owner = normalizeDID(ownerDID);
8
+ return {
9
+ owner,
10
+ subjectKey: `${connector}:${owner}`
11
+ };
12
+ }
package/lib/schema.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { ConnectorSyncEventPayload } from '@kubun/connector';
2
2
  import type { SchemaExtension } from '@kubun/engine';
3
3
  import type { AdaptivePolicy } from '@kubun/plugin-workflow-api';
4
- import type { EventEmitter } from '@sozai/event';
4
+ import type { EventEmitter, EventsSource } from '@sozai/event';
5
+ import type { ConnectorLifecycleEventName, ConnectorLifecycleEventPayload } from './manager.js';
5
6
  import type { ConnectorRegistry } from './registry.js';
6
7
  import type { SignedDocumentWriter } from './sync/processor.js';
7
8
  /**
@@ -19,6 +20,7 @@ export type ConnectorState = {
19
20
  lastSyncedAt: string | null;
20
21
  entityCount: number | null;
21
22
  error: string | null;
23
+ workflowStatusError: 'WORKFLOW_UNAVAILABLE' | null;
22
24
  };
23
25
  /**
24
26
  * Input/output types for connector auth mutations.
@@ -139,6 +141,47 @@ export type ConnectorSyncEventEmitter = EventEmitter<{
139
141
  * potentially never.
140
142
  */
141
143
  export declare function subscribeToConnectorSyncEvents(emitter: ConnectorSyncEventEmitter, connector?: string | null): AsyncIterableIterator<ConnectorSyncEventResult>;
144
+ /**
145
+ * Merged lifecycle event payload for subscriptions (GraphQL result type). Flat
146
+ * and nullable: a given event carries only the fields its variant defines, and
147
+ * the rest resolve to null (mirrors `ConnectorSyncEventResult`).
148
+ */
149
+ export type ConnectorLifecycleEventResult = {
150
+ type: ConnectorLifecycleEventName;
151
+ ownerDID: string;
152
+ provider: string | null;
153
+ connector: string | null;
154
+ connectors: Array<string> | null;
155
+ scopes: Array<string> | null;
156
+ expiresAt: number | null;
157
+ reason: string | null;
158
+ subjectKey: string | null;
159
+ };
160
+ /**
161
+ * Flatten a merged lifecycle payload into the GraphQL result shape, filling the
162
+ * fields absent from the variant with null.
163
+ */
164
+ export declare function toConnectorLifecycleEventResult(event: ConnectorLifecycleEventPayload): ConnectorLifecycleEventResult;
165
+ /**
166
+ * Subscribe to the merged lifecycle channel as a single viewer, yielding GraphQL
167
+ * result shapes. Every event is filtered by `ownerDID` against the caller's
168
+ * already-normalized `viewerDID`, so one viewer never observes another's auth
169
+ * activity; an optional `connector` further restricts delivery, matching both
170
+ * the auth-family `connectors[]` membership and the periodicSync single
171
+ * `connector`. Built on the same manual async iterator as
172
+ * `subscribeToConnectorSyncEvents` so a consumer's `return()` removes the
173
+ * emitter listener immediately rather than leaking behind a parked read.
174
+ *
175
+ * The emitter is the manager's listen-only `EventsSource`; `fromEmitter` only
176
+ * reads its `.on`, but its parameter is typed to the concrete emitter class, so
177
+ * the source is narrowed to it here.
178
+ */
179
+ export declare function subscribeToConnectorLifecycleEvents(emitter: EventsSource<{
180
+ lifecycle: ConnectorLifecycleEventPayload;
181
+ }>, opts: {
182
+ viewerDID: string;
183
+ connector?: string | null;
184
+ }): AsyncIterableIterator<ConnectorLifecycleEventResult>;
142
185
  /**
143
186
  * Per-request context methods for the Connector query and mutation fields.
144
187
  * Provided by the context factory when registry + credentials are configured.
@@ -153,6 +196,7 @@ export type ConnectorQueryContext = {
153
196
  completeAuth: (args: CompleteConnectorAuthInput) => Promise<CompleteConnectorAuthOutput>;
154
197
  triggerSync: (args: SyncTriggerInput) => Promise<SyncTriggerOutput>;
155
198
  subscribeToSyncEvents: (connector?: string | null) => AsyncIterable<ConnectorSyncEventResult>;
199
+ subscribeToLifecycleEvents: (connector?: string | null) => AsyncIterable<ConnectorLifecycleEventResult>;
156
200
  executeAction?: (args: ConnectorActionInput, writeDocument: SignedDocumentWriter) => Promise<ConnectorActionResult>;
157
201
  grantWriteCapability?: (args: {
158
202
  connector: string;
package/lib/schema.js CHANGED
@@ -58,6 +58,107 @@ import { fromEmitter } from '@sozai/generator';
58
58
  }
59
59
  };
60
60
  }
61
+ /**
62
+ * Flatten a merged lifecycle payload into the GraphQL result shape, filling the
63
+ * fields absent from the variant with null.
64
+ */ export function toConnectorLifecycleEventResult(event) {
65
+ const result = {
66
+ type: event.type,
67
+ ownerDID: event.ownerDID,
68
+ provider: null,
69
+ connector: null,
70
+ connectors: null,
71
+ scopes: null,
72
+ expiresAt: null,
73
+ reason: null,
74
+ subjectKey: null
75
+ };
76
+ switch(event.type){
77
+ case 'connector:authenticated':
78
+ result.provider = event.provider;
79
+ result.connectors = event.connectors;
80
+ result.scopes = event.scopes;
81
+ break;
82
+ case 'connector:deauthenticated':
83
+ result.provider = event.provider;
84
+ result.connectors = event.connectors;
85
+ break;
86
+ case 'connector:credentialRefreshed':
87
+ result.provider = event.provider;
88
+ result.connectors = event.connectors;
89
+ result.scopes = event.scopes;
90
+ result.expiresAt = event.expiresAt ?? null;
91
+ break;
92
+ case 'connector:authRequired':
93
+ result.provider = event.provider;
94
+ result.connectors = event.connectors;
95
+ result.reason = event.reason;
96
+ break;
97
+ case 'periodicSync:enabled':
98
+ case 'periodicSync:disabled':
99
+ result.connector = event.connector;
100
+ result.subjectKey = event.subjectKey;
101
+ break;
102
+ }
103
+ return result;
104
+ }
105
+ /**
106
+ * Subscribe to the merged lifecycle channel as a single viewer, yielding GraphQL
107
+ * result shapes. Every event is filtered by `ownerDID` against the caller's
108
+ * already-normalized `viewerDID`, so one viewer never observes another's auth
109
+ * activity; an optional `connector` further restricts delivery, matching both
110
+ * the auth-family `connectors[]` membership and the periodicSync single
111
+ * `connector`. Built on the same manual async iterator as
112
+ * `subscribeToConnectorSyncEvents` so a consumer's `return()` removes the
113
+ * emitter listener immediately rather than leaking behind a parked read.
114
+ *
115
+ * The emitter is the manager's listen-only `EventsSource`; `fromEmitter` only
116
+ * reads its `.on`, but its parameter is typed to the concrete emitter class, so
117
+ * the source is narrowed to it here.
118
+ */ export function subscribeToConnectorLifecycleEvents(emitter, opts) {
119
+ const { viewerDID, connector } = opts;
120
+ const filter = (event)=>{
121
+ if (event.ownerDID !== viewerDID) {
122
+ return false;
123
+ }
124
+ if (connector == null) {
125
+ return true;
126
+ }
127
+ return 'connectors' in event ? event.connectors.includes(connector) : event.connector === connector;
128
+ };
129
+ const generator = fromEmitter(emitter, 'lifecycle', {
130
+ filter
131
+ });
132
+ return {
133
+ [Symbol.asyncIterator] () {
134
+ return this;
135
+ },
136
+ async next () {
137
+ const { done, value } = await generator.next();
138
+ return done ? {
139
+ done: true,
140
+ value: undefined
141
+ } : {
142
+ done: false,
143
+ value: toConnectorLifecycleEventResult(value)
144
+ };
145
+ },
146
+ async return () {
147
+ await generator.return();
148
+ return {
149
+ done: true,
150
+ value: undefined
151
+ };
152
+ },
153
+ async throw (reason) {
154
+ await generator.throw(reason);
155
+ return {
156
+ done: true,
157
+ value: undefined
158
+ };
159
+ }
160
+ };
161
+ }
61
162
  function requireConnector(ctx) {
62
163
  if (ctx.connector == null) {
63
164
  throw new Error('connector plugin is not wired into this context');
@@ -116,6 +217,7 @@ type Connector implements Node {
116
217
  lastSyncedAt: String
117
218
  entityCount: Int
118
219
  error: String
220
+ workflowStatusError: String
119
221
  }
120
222
 
121
223
  type StartConnectorAuthResult {
@@ -144,6 +246,18 @@ type ConnectorSyncEvent {
144
246
  error: String
145
247
  }
146
248
 
249
+ type ConnectorLifecycleEvent {
250
+ type: String!
251
+ ownerDID: String!
252
+ provider: String
253
+ connector: String
254
+ connectors: [String!]
255
+ scopes: [String!]
256
+ expiresAt: Float
257
+ reason: String
258
+ subjectKey: String
259
+ }
260
+
147
261
  type ConnectorActionError {
148
262
  code: String!
149
263
  message: String!
@@ -175,6 +289,7 @@ extend type Mutation {
175
289
 
176
290
  extend type Subscription {
177
291
  connectorSyncEvents(connector: String): ConnectorSyncEvent!
292
+ connectorLifecycleEvents(connector: String): ConnectorLifecycleEvent!
178
293
  }
179
294
  `);
180
295
  // Recurring-sync control. Gated because it references `PeriodicSync`, which is
@@ -398,6 +513,13 @@ input ConnectorUpdate${modelName}Input {
398
513
  const ctx = context;
399
514
  return requireConnector(ctx).subscribeToSyncEvents(args.connector);
400
515
  }
516
+ },
517
+ connectorLifecycleEvents: {
518
+ resolve: (event)=>event,
519
+ subscribe: (_source, args, context)=>{
520
+ const ctx = context;
521
+ return requireConnector(ctx).subscribeToLifecycleEvents(args.connector);
522
+ }
401
523
  }
402
524
  };
403
525
  return {
@@ -10,7 +10,7 @@ import type { MutateDocuments } from './processor.js';
10
10
  * this type can be replaced with the concrete class.
11
11
  */
12
12
  export type SyncEventEmitter = {
13
- emitSyncEvent(event: ConnectorSyncEventPayload): Promise<void>;
13
+ emitSyncEvent(event: ConnectorSyncEventPayload): void;
14
14
  };
15
15
  export type OrchestrateSyncParams = {
16
16
  connectorName: string;
@@ -33,6 +33,16 @@ export type OrchestrateSyncParams = {
33
33
  * imports upsert by unique key).
34
34
  */
35
35
  inFlight?: Set<string>;
36
+ /**
37
+ * Signal that this sync bailed because the provider credential is absent, so a
38
+ * consumer can prompt (re)authorization. Additive to the sync `error` event —
39
+ * not a replacement. Fired only for a missing credential, never for an absent
40
+ * server provider.
41
+ */
42
+ emitAuthRequired?: (params: {
43
+ provider: string;
44
+ ownerDID: string;
45
+ }) => void;
36
46
  };
37
47
  export type OrchestrateSyncResult = {
38
48
  status: 'started' | 'already_syncing' | 'error';
@@ -56,6 +56,12 @@ export async function orchestrateSync(params) {
56
56
  const credential = providerName ? await credentialProvider.get(providerName, ownerDID) : null;
57
57
  if (providerName != null && credential == null) {
58
58
  release();
59
+ // Additive to the error event below: the sync stream still sees the failure,
60
+ // and a lifecycle consumer additionally learns (re)authorization is needed.
61
+ params.emitAuthRequired?.({
62
+ provider: providerName,
63
+ ownerDID
64
+ });
59
65
  await emitError(`no credential for provider "${providerName}"`);
60
66
  return {
61
67
  status: 'error'
@@ -33,6 +33,7 @@ export type ConnectorSyncWorkflowDefinition = {
33
33
  name: string;
34
34
  };
35
35
  handlers: Record<string, ConnectorSyncHandler>;
36
+ managed: true;
36
37
  };
37
38
  export type ConnectorSyncWorkflowParams = {
38
39
  registry: ConnectorRegistry;
@@ -43,6 +44,16 @@ export type ConnectorSyncWorkflowParams = {
43
44
  mutateDocuments?: MutateDocuments;
44
45
  boundary?: SyncBoundary;
45
46
  logger: Logger;
47
+ /**
48
+ * Signal that a sync cannot proceed because the provider credential is absent,
49
+ * so a consumer can prompt (re)authorization. Fired only for a genuinely
50
+ * missing credential — never for an absent server provider, which is an
51
+ * ordinary offline/configuration outcome.
52
+ */
53
+ emitAuthRequired?: (params: {
54
+ provider: string;
55
+ ownerDID: string;
56
+ }) => void;
46
57
  };
47
58
  /**
48
59
  * Build the `connector-sync` workflow definition. One sync pass is a self-looping
@@ -14,7 +14,7 @@ import { MAX_LOGGED_ERRORS } from './processor.js';
14
14
  * definitions (two "boots" over one DB) do not share iterators — which is what
15
15
  * makes crash-recovery re-open the provider from the checkpoint.
16
16
  */ export function createConnectorSyncWorkflow(params) {
17
- const { registry, credentialProvider, stateStore, syncEventEmitter, stores, mutateDocuments, logger } = params;
17
+ const { registry, credentialProvider, stateStore, syncEventEmitter, stores, mutateDocuments, logger, emitAuthRequired } = params;
18
18
  const sessions = new Map();
19
19
  const sessionKey = (state)=>`${state.connectorName}:${state.ownerDID}`;
20
20
  const effectiveBoundary = params.boundary ?? {
@@ -64,6 +64,15 @@ import { MAX_LOGGED_ERRORS } from './processor.js';
64
64
  lastSyncedAt: new Date().toISOString(),
65
65
  failedSample: []
66
66
  };
67
+ // Only a genuinely absent credential asks for (re)authorization; an absent
68
+ // server provider stays a silent configuration outcome. Both still end
69
+ // offline (the event is additive, not a change to the offline outcome).
70
+ if (providerName != null && credential == null) {
71
+ emitAuthRequired?.({
72
+ provider: providerName,
73
+ ownerDID
74
+ });
75
+ }
67
76
  return {
68
77
  status: 'end',
69
78
  state: offlineState,
@@ -126,6 +135,20 @@ import { MAX_LOGGED_ERRORS } from './processor.js';
126
135
  }
127
136
  const providerName = connector.auth.provider !== 'device' ? connector.auth.provider : null;
128
137
  const credential = providerName ? await credentialProvider.get(providerName, state.ownerDID) : null;
138
+ // A crash-recovered batch whose credential has since been removed cannot
139
+ // resume: signal (re)authorization and end offline rather than opening the
140
+ // provider with an empty credential (which would fail mid-sync ⇒ error).
141
+ if (providerName != null && credential == null) {
142
+ emitAuthRequired?.({
143
+ provider: providerName,
144
+ ownerDID: state.ownerDID
145
+ });
146
+ return {
147
+ status: 'end',
148
+ state,
149
+ outcome: 'offline'
150
+ };
151
+ }
129
152
  if (connector.serverProvider == null) {
130
153
  throw new Error(`Connector "${state.connectorName}" has no server provider`);
131
154
  }
@@ -258,7 +281,8 @@ import { MAX_LOGGED_ERRORS } from './processor.js';
258
281
  start,
259
282
  batch,
260
283
  finalize
261
- }
284
+ },
285
+ managed: true
262
286
  }
263
287
  };
264
288
  }
@@ -1,8 +1,11 @@
1
- import type { CredentialProvider } from '@kubun/credential-types';
1
+ import type { Credential, CredentialProvider } from '@kubun/credential-types';
2
2
  import { HLC } from '@kubun/hlc';
3
3
  import { getDelegationStore } from '@kubun/store-delegation';
4
4
  import type { ConnectorRegistry } from './registry.js';
5
5
  import type { ConnectorWriteGrant } from './schema.js';
6
+ type CredentialFacade = CredentialProvider & {
7
+ peek?(providerName: string, ownerDID: string): Promise<Credential | null>;
8
+ };
6
9
  export type WriteGrantContextParams = {
7
10
  registry: ConnectorRegistry;
8
11
  /** The server identity a viewer delegates its write authority to (`aud`). */
@@ -10,8 +13,12 @@ export type WriteGrantContextParams = {
10
13
  /** The calling viewer (raw, unnormalized) — the grantor of every cap. */
11
14
  viewerDID: string;
12
15
  stores: Parameters<typeof getDelegationStore>[0];
13
- credentialProvider: CredentialProvider;
16
+ credentialProvider: CredentialFacade;
14
17
  hlc: HLC;
18
+ onCredentialRemoved?: (params: {
19
+ provider: string;
20
+ ownerDID: string;
21
+ }) => void;
15
22
  };
16
23
  export type WriteGrantContext = {
17
24
  grantWriteCapability(args: {
@@ -33,3 +40,4 @@ export type WriteGrantContext = {
33
40
  * stored `resource` string handled here is only the revoke/list selector.
34
41
  */
35
42
  export declare function createWriteGrantContext(params: WriteGrantContextParams): WriteGrantContext;
43
+ export {};
@@ -240,8 +240,17 @@ async function revokeCapsSubsetOf(delegationStore, grantor, audience, allowed) {
240
240
  }
241
241
  const delegationStore = await getDelegationStore(stores);
242
242
  const removed = await revokeCapsSubsetOf(delegationStore, viewerDID, audienceDID, providerURNs);
243
- const credentialExisted = await credentialProvider.get(provider, viewerDID) != null;
243
+ // Test existence with the non-refreshing peek (falling back to `get` only
244
+ // when a caller supplies no peek) so disconnecting an expiring credential
245
+ // does not trigger a transparent refresh right before the delete.
246
+ const credentialExisted = (credentialProvider.peek != null ? await credentialProvider.peek(provider, viewerDID) : await credentialProvider.get(provider, viewerDID)) != null;
244
247
  await credentialProvider.delete(provider, viewerDID);
248
+ if (credentialExisted) {
249
+ params.onCredentialRemoved?.({
250
+ provider,
251
+ ownerDID: viewerDID
252
+ });
253
+ }
245
254
  return removed > 0 || credentialExisted;
246
255
  },
247
256
  connectorWriteGrants: async ()=>{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/plugin-connector",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "license": "see LICENSE.md",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -18,7 +18,7 @@
18
18
  "@kokuin/jwe": "^0.1.0",
19
19
  "@kokuin/token": "^0.5.0",
20
20
  "@kubun/connector": "^0.14.0",
21
- "@kubun/credential": "^0.14.1",
21
+ "@kubun/credential": "^0.14.2",
22
22
  "@kubun/credential-types": "^0.14.0",
23
23
  "@kubun/db": "^0.14.0",
24
24
  "@kubun/engine": "^0.14.1",
@@ -27,7 +27,7 @@
27
27
  "@kubun/id": "^0.14.0",
28
28
  "@kubun/logger": "^0.14.0",
29
29
  "@kubun/plugin-blob-api": "^0.14.0",
30
- "@kubun/plugin-workflow-api": "^0.14.0",
30
+ "@kubun/plugin-workflow-api": "^0.14.1",
31
31
  "@kubun/protocol": "^0.14.1",
32
32
  "@kubun/service-credential-api": "^0.14.0",
33
33
  "@kubun/store-connector": "^0.14.0",
@@ -56,11 +56,11 @@
56
56
  "@kubun/plugin-credential": "^0.14.0",
57
57
  "@kubun/plugin-service-client": "^0.14.0",
58
58
  "@kubun/plugin-service-server": "^0.14.0",
59
- "@kubun/plugin-workflow": "^0.14.0",
59
+ "@kubun/plugin-workflow": "^0.14.1",
60
60
  "@kubun/service-controller-log-api": "^0.14.0",
61
61
  "@kubun/store-blob": "^0.14.0",
62
62
  "@kubun/store-controller": "^0.14.0",
63
- "@kubun/store-workflow": "^0.14.0",
63
+ "@kubun/store-workflow": "^0.14.1",
64
64
  "@kubun/test-utils": "^0.13.0",
65
65
  "@testcontainers/postgresql": "^12.1.0",
66
66
  "get-port": "^7.2.0"