@cat-factory/integrations 0.118.0 → 0.119.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/dist/modules/capabilityCredentials/CapabilityCredentialsService.d.ts +36 -8
- package/dist/modules/capabilityCredentials/CapabilityCredentialsService.d.ts.map +1 -1
- package/dist/modules/capabilityCredentials/CapabilityCredentialsService.js +119 -34
- package/dist/modules/capabilityCredentials/CapabilityCredentialsService.js.map +1 -1
- package/package.json +4 -4
|
@@ -30,6 +30,14 @@ export interface CapabilityCredentialsServiceDependencies {
|
|
|
30
30
|
* `BinaryGeneratorSource` rather than a registry anyway, which only the composition root can
|
|
31
31
|
* supply.
|
|
32
32
|
*
|
|
33
|
+
* CONCURRENCY: the row is ONE sealed blob holding the whole set, so the per-key writes
|
|
34
|
+
* ({@link put}, {@link remove}) are read-modify-write over it and ride a rev-guarded
|
|
35
|
+
* `compareAndSwap`: a blind upsert would let two operators saving DIFFERENT keys silently
|
|
36
|
+
* destroy each other's, with the loser's save still returning success. On a lost race the
|
|
37
|
+
* mutation reloads and re-applies on the winner's snapshot (it is a pure single-key edit, so
|
|
38
|
+
* re-application is trivially idempotent). The whole-set {@link set} stays a blind write on
|
|
39
|
+
* purpose: replacing whatever is stored IS its semantics.
|
|
40
|
+
*
|
|
33
41
|
* {@link resolveValues} is the one place a value is decrypted, and its result reaches nothing but
|
|
34
42
|
* the job body.
|
|
35
43
|
*/
|
|
@@ -47,17 +55,24 @@ export declare class CapabilityCredentialsService {
|
|
|
47
55
|
*
|
|
48
56
|
* A whole-set REPLACE rather than a merge, because the client cannot merge: it never received
|
|
49
57
|
* the values, so a partial write would have to mean "leave the ones I did not send alone",
|
|
50
|
-
* which is indistinguishable on the wire from "remove them". {@link
|
|
51
|
-
*
|
|
58
|
+
* which is indistinguishable on the wire from "remove them". {@link put} and {@link remove}
|
|
59
|
+
* are the narrow operations that would otherwise need that distinction.
|
|
52
60
|
*/
|
|
53
61
|
set(workspaceId: string, input: UpsertCapabilityCredentialsInput): Promise<CapabilityCredentialRef[]>;
|
|
54
62
|
/**
|
|
55
|
-
*
|
|
63
|
+
* Set ONE credential's value, leaving the rest sealed as they are. Replaces the value when the
|
|
64
|
+
* key is already stored, appends it otherwise.
|
|
56
65
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
66
|
+
* The narrow twin of {@link remove}, and the write a checklist UI actually performs: the
|
|
67
|
+
* client holds no values, so it can neither re-send the set nor express "leave the others
|
|
68
|
+
* alone" through {@link set}. Rev-guarded (see the class doc), so two operators saving
|
|
69
|
+
* different keys at the same moment both land.
|
|
70
|
+
*/
|
|
71
|
+
put(workspaceId: string, key: string, value: string): Promise<CapabilityCredentialRef[]>;
|
|
72
|
+
/**
|
|
73
|
+
* Remove ONE stored credential, leaving the rest sealed as they are. Re-seals the survivors
|
|
74
|
+
* rather than editing the blob in place, rev-guarded like {@link put}; emptying the set
|
|
75
|
+
* deletes the row through the same guard, so a concurrent save's key cannot be swept away.
|
|
61
76
|
*/
|
|
62
77
|
remove(workspaceId: string, key: string): Promise<CapabilityCredentialRef[]>;
|
|
63
78
|
/**
|
|
@@ -66,7 +81,20 @@ export declare class CapabilityCredentialsService {
|
|
|
66
81
|
* fallback (where a facade wired one) should answer instead.
|
|
67
82
|
*/
|
|
68
83
|
resolveValues(workspaceId: string): Promise<CapabilityCredentialEntry[]>;
|
|
69
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Apply a pure single-key mutation under OPTIMISTIC CONCURRENCY: load, run `apply`, then
|
|
86
|
+
* `compareAndSwap` (or the rev-guarded delete when the set empties); on a lost race reload and
|
|
87
|
+
* re-apply on the winner's snapshot, bounded by {@link MAX_MUTATE_ATTEMPTS}.
|
|
88
|
+
*
|
|
89
|
+
* `apply` returns the next entry set, or null for "nothing to change" (a duplicate delete),
|
|
90
|
+
* which answers with the current summary untouched. `touchedKey` is the one key whose
|
|
91
|
+
* `updatedAt` this write may honestly stamp: "last set" is a per-key fact, so every OTHER
|
|
92
|
+
* entry keeps the timestamp the stored summary already carries. A write that re-stamped the
|
|
93
|
+
* whole set would falsify every neighbour's date.
|
|
94
|
+
*/
|
|
95
|
+
private mutate;
|
|
96
|
+
/** Decrypt and validate the sealed entry blob; an absent row is an empty set. */
|
|
97
|
+
private decryptEntries;
|
|
70
98
|
/** Parse the persisted non-secret summary, tolerating a corrupt row (the view still loads). */
|
|
71
99
|
private parseSummary;
|
|
72
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CapabilityCredentialsService.d.ts","sourceRoot":"","sources":["../../../src/modules/capabilityCredentials/CapabilityCredentialsService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,8BAA8B,EAC9B,KAAK,EACL,YAAY,EACb,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"CapabilityCredentialsService.d.ts","sourceRoot":"","sources":["../../../src/modules/capabilityCredentials/CapabilityCredentialsService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,8BAA8B,EAC9B,KAAK,EACL,YAAY,EACb,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACvB,gCAAgC,EACjC,MAAM,wBAAwB,CAAA;AAO/B;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,uCAAuC,CAAA;AAUtF,MAAM,WAAW,wCAAwC;IACvD,8BAA8B,EAAE,8BAA8B,CAAA;IAC9D,4FAA4F;IAC5F,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,4BAA4B;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,wCAAwC,EAAI;IAE/E;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAGxE;IAED;;;;;;;;OAQG;IACG,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAoBpC;IAED;;;;;;;;OAQG;IACG,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAe7F;IAED;;;;OAIG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAQjF;IAED;;;;OAIG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAE7E;IAED;;;;;;;;;;OAUG;YACW,MAAM;IA0CpB,iFAAiF;YACnE,cAAc;IAS5B,+FAA+F;IAC/F,OAAO,CAAC,YAAY;CAerB"}
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConflictError, ValidationError } from '@cat-factory/kernel';
|
|
2
|
+
import { MAX_CAPABILITY_CREDENTIALS, capabilityCredentialsSummary, parseCapabilityCredentialEntries, } from '@cat-factory/contracts';
|
|
2
3
|
/**
|
|
3
4
|
* HKDF domain tag separating the sealed capability-credential blob from every other cipher
|
|
4
5
|
* (mirrors {@link TEST_SECRETS_CIPHER_INFO} et al). The facade builds a `WebCryptoSecretCipher`
|
|
5
6
|
* keyed by `ENCRYPTION_KEY` with this info tag.
|
|
6
7
|
*/
|
|
7
8
|
export const CAPABILITY_CREDENTIALS_CIPHER_INFO = 'cat-factory:capability-credentials';
|
|
9
|
+
/**
|
|
10
|
+
* How many times a contended per-key mutation reloads and re-applies before giving up with a
|
|
11
|
+
* 409. Matches `IterativeReviewService`'s budget: the contending writers here are human saves in
|
|
12
|
+
* two browser tabs, so a handful of retries covers real contention while still failing loudly on
|
|
13
|
+
* a pathological hot row.
|
|
14
|
+
*/
|
|
15
|
+
const MAX_MUTATE_ATTEMPTS = 8;
|
|
8
16
|
/**
|
|
9
17
|
* Owns a workspace's capability credentials: the tenant-scoped, sealed home for the secrets a
|
|
10
18
|
* tool server or a generative binary integration declares by name.
|
|
@@ -23,6 +31,14 @@ export const CAPABILITY_CREDENTIALS_CIPHER_INFO = 'cat-factory:capability-creden
|
|
|
23
31
|
* `BinaryGeneratorSource` rather than a registry anyway, which only the composition root can
|
|
24
32
|
* supply.
|
|
25
33
|
*
|
|
34
|
+
* CONCURRENCY: the row is ONE sealed blob holding the whole set, so the per-key writes
|
|
35
|
+
* ({@link put}, {@link remove}) are read-modify-write over it and ride a rev-guarded
|
|
36
|
+
* `compareAndSwap`: a blind upsert would let two operators saving DIFFERENT keys silently
|
|
37
|
+
* destroy each other's, with the loser's save still returning success. On a lost race the
|
|
38
|
+
* mutation reloads and re-applies on the winner's snapshot (it is a pure single-key edit, so
|
|
39
|
+
* re-application is trivially idempotent). The whole-set {@link set} stays a blind write on
|
|
40
|
+
* purpose: replacing whatever is stored IS its semantics.
|
|
41
|
+
*
|
|
26
42
|
* {@link resolveValues} is the one place a value is decrypted, and its result reaches nothing but
|
|
27
43
|
* the job body.
|
|
28
44
|
*/
|
|
@@ -45,36 +61,68 @@ export class CapabilityCredentialsService {
|
|
|
45
61
|
*
|
|
46
62
|
* A whole-set REPLACE rather than a merge, because the client cannot merge: it never received
|
|
47
63
|
* the values, so a partial write would have to mean "leave the ones I did not send alone",
|
|
48
|
-
* which is indistinguishable on the wire from "remove them". {@link
|
|
49
|
-
*
|
|
64
|
+
* which is indistinguishable on the wire from "remove them". {@link put} and {@link remove}
|
|
65
|
+
* are the narrow operations that would otherwise need that distinction.
|
|
50
66
|
*/
|
|
51
67
|
async set(workspaceId, input) {
|
|
52
68
|
if (input.entries.length === 0) {
|
|
53
69
|
await this.deps.capabilityCredentialRepository.delete(workspaceId);
|
|
54
70
|
return [];
|
|
55
71
|
}
|
|
56
|
-
|
|
72
|
+
const now = this.deps.clock.now();
|
|
73
|
+
const existing = await this.deps.capabilityCredentialRepository.get(workspaceId);
|
|
74
|
+
// Every value in the set was just (re)typed, so every key is honestly stamped `now`.
|
|
75
|
+
const summary = capabilityCredentialsSummary(input.entries, now);
|
|
76
|
+
await this.deps.capabilityCredentialRepository.upsert({
|
|
77
|
+
workspaceId,
|
|
78
|
+
credentials: await this.deps.secretCipher.encrypt(JSON.stringify(input.entries)),
|
|
79
|
+
summary: JSON.stringify(summary),
|
|
80
|
+
// The insert value; a conflicting update bumps the STORED rev in SQL instead, so the rev
|
|
81
|
+
// stays monotonic under this blind write and a concurrent compareAndSwap reliably loses.
|
|
82
|
+
rev: 0,
|
|
83
|
+
createdAt: existing?.createdAt ?? now,
|
|
84
|
+
updatedAt: now,
|
|
85
|
+
});
|
|
86
|
+
return summary;
|
|
57
87
|
}
|
|
58
88
|
/**
|
|
59
|
-
*
|
|
89
|
+
* Set ONE credential's value, leaving the rest sealed as they are. Replaces the value when the
|
|
90
|
+
* key is already stored, appends it otherwise.
|
|
60
91
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
92
|
+
* The narrow twin of {@link remove}, and the write a checklist UI actually performs: the
|
|
93
|
+
* client holds no values, so it can neither re-send the set nor express "leave the others
|
|
94
|
+
* alone" through {@link set}. Rev-guarded (see the class doc), so two operators saving
|
|
95
|
+
* different keys at the same moment both land.
|
|
96
|
+
*/
|
|
97
|
+
async put(workspaceId, key, value) {
|
|
98
|
+
return this.mutate(workspaceId, key, (entries) => {
|
|
99
|
+
const existing = entries.findIndex((entry) => entry.key === key);
|
|
100
|
+
if (existing === -1 && entries.length >= MAX_CAPABILITY_CREDENTIALS) {
|
|
101
|
+
throw new ValidationError(`at most ${MAX_CAPABILITY_CREDENTIALS} capability credentials per workspace`, { reason: 'capability_credential_limit' });
|
|
102
|
+
}
|
|
103
|
+
const next = [...entries];
|
|
104
|
+
// Replace IN PLACE for a known key, so re-typing a value does not reorder the stored set.
|
|
105
|
+
if (existing === -1)
|
|
106
|
+
next.push({ key, value });
|
|
107
|
+
else
|
|
108
|
+
next[existing] = { key, value };
|
|
109
|
+
return next;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Remove ONE stored credential, leaving the rest sealed as they are. Re-seals the survivors
|
|
114
|
+
* rather than editing the blob in place, rev-guarded like {@link put}; emptying the set
|
|
115
|
+
* deletes the row through the same guard, so a concurrent save's key cannot be swept away.
|
|
65
116
|
*/
|
|
66
117
|
async remove(workspaceId, key) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return [];
|
|
76
|
-
}
|
|
77
|
-
return this.write(workspaceId, remaining);
|
|
118
|
+
return this.mutate(workspaceId, null, (entries) => {
|
|
119
|
+
const remaining = entries.filter((entry) => entry.key !== key);
|
|
120
|
+
// Nothing matched: answer with the current state rather than rewriting the blob, so a
|
|
121
|
+
// duplicate delete is a no-op instead of a pointless re-seal.
|
|
122
|
+
if (remaining.length === entries.length)
|
|
123
|
+
return null;
|
|
124
|
+
return remaining;
|
|
125
|
+
});
|
|
78
126
|
}
|
|
79
127
|
/**
|
|
80
128
|
* The DECRYPTED credential set for a workspace — read once per dispatch by the composed
|
|
@@ -82,24 +130,61 @@ export class CapabilityCredentialsService {
|
|
|
82
130
|
* fallback (where a facade wired one) should answer instead.
|
|
83
131
|
*/
|
|
84
132
|
async resolveValues(workspaceId) {
|
|
85
|
-
|
|
133
|
+
return this.decryptEntries(await this.deps.capabilityCredentialRepository.get(workspaceId));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Apply a pure single-key mutation under OPTIMISTIC CONCURRENCY: load, run `apply`, then
|
|
137
|
+
* `compareAndSwap` (or the rev-guarded delete when the set empties); on a lost race reload and
|
|
138
|
+
* re-apply on the winner's snapshot, bounded by {@link MAX_MUTATE_ATTEMPTS}.
|
|
139
|
+
*
|
|
140
|
+
* `apply` returns the next entry set, or null for "nothing to change" (a duplicate delete),
|
|
141
|
+
* which answers with the current summary untouched. `touchedKey` is the one key whose
|
|
142
|
+
* `updatedAt` this write may honestly stamp: "last set" is a per-key fact, so every OTHER
|
|
143
|
+
* entry keeps the timestamp the stored summary already carries. A write that re-stamped the
|
|
144
|
+
* whole set would falsify every neighbour's date.
|
|
145
|
+
*/
|
|
146
|
+
async mutate(workspaceId, touchedKey, apply) {
|
|
147
|
+
const repo = this.deps.capabilityCredentialRepository;
|
|
148
|
+
for (let attempt = 0; attempt < MAX_MUTATE_ATTEMPTS; attempt++) {
|
|
149
|
+
const record = await repo.get(workspaceId);
|
|
150
|
+
const next = apply(await this.decryptEntries(record));
|
|
151
|
+
if (next === null)
|
|
152
|
+
return this.parseSummary(record);
|
|
153
|
+
if (next.length === 0) {
|
|
154
|
+
if (!record)
|
|
155
|
+
return [];
|
|
156
|
+
if (await repo.deleteIfRev(workspaceId, record.rev))
|
|
157
|
+
return [];
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const now = this.deps.clock.now();
|
|
161
|
+
const prior = new Map(this.parseSummary(record).map((ref) => [ref.key, ref.updatedAt]));
|
|
162
|
+
const summary = next.map((entry) => ({
|
|
163
|
+
key: entry.key,
|
|
164
|
+
updatedAt: entry.key === touchedKey ? now : (prior.get(entry.key) ?? now),
|
|
165
|
+
}));
|
|
166
|
+
const swapped = await repo.compareAndSwap({
|
|
167
|
+
workspaceId,
|
|
168
|
+
credentials: await this.deps.secretCipher.encrypt(JSON.stringify(next)),
|
|
169
|
+
summary: JSON.stringify(summary),
|
|
170
|
+
rev: (record?.rev ?? -1) + 1,
|
|
171
|
+
createdAt: record?.createdAt ?? now,
|
|
172
|
+
updatedAt: now,
|
|
173
|
+
}, record?.rev ?? null);
|
|
174
|
+
if (swapped)
|
|
175
|
+
return summary;
|
|
176
|
+
// Lost the race: loop back, reload, re-apply on the winner's snapshot.
|
|
177
|
+
}
|
|
178
|
+
// No `reason` code, same call as ReviewContendedError: the SPA has no conflict-specific
|
|
179
|
+
// handling beyond "retry", which the message already says.
|
|
180
|
+
throw new ConflictError(`capability credentials for workspace '${workspaceId}' are being modified concurrently; retry`);
|
|
181
|
+
}
|
|
182
|
+
/** Decrypt and validate the sealed entry blob; an absent row is an empty set. */
|
|
183
|
+
async decryptEntries(record) {
|
|
86
184
|
if (!record)
|
|
87
185
|
return [];
|
|
88
186
|
return parseCapabilityCredentialEntries(JSON.parse(await this.deps.secretCipher.decrypt(record.credentials)));
|
|
89
187
|
}
|
|
90
|
-
async write(workspaceId, entries) {
|
|
91
|
-
const now = this.deps.clock.now();
|
|
92
|
-
const existing = await this.deps.capabilityCredentialRepository.get(workspaceId);
|
|
93
|
-
const summary = capabilityCredentialsSummary(entries, now);
|
|
94
|
-
await this.deps.capabilityCredentialRepository.upsert({
|
|
95
|
-
workspaceId,
|
|
96
|
-
credentials: await this.deps.secretCipher.encrypt(JSON.stringify(entries)),
|
|
97
|
-
summary: JSON.stringify(summary),
|
|
98
|
-
createdAt: existing?.createdAt ?? now,
|
|
99
|
-
updatedAt: now,
|
|
100
|
-
});
|
|
101
|
-
return summary;
|
|
102
|
-
}
|
|
103
188
|
/** Parse the persisted non-secret summary, tolerating a corrupt row (the view still loads). */
|
|
104
189
|
parseSummary(record) {
|
|
105
190
|
if (!record)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CapabilityCredentialsService.js","sourceRoot":"","sources":["../../../src/modules/capabilityCredentials/CapabilityCredentialsService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CapabilityCredentialsService.js","sourceRoot":"","sources":["../../../src/modules/capabilityCredentials/CapabilityCredentialsService.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAMpE,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,wBAAwB,CAAA;AAE/B;;;;GAIG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,oCAAoC,CAAA;AAEtF;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,CAAA;AAS7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,4BAA4B;IACV,IAAI;IAAjC,YAA6B,IAA8C;oBAA9C,IAAI;IAA6C,CAAC;IAE/E;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CACP,WAAmB,EACnB,KAAuC;QAEvC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YAClE,OAAO,EAAE,CAAA;QACX,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;QACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAChF,qFAAqF;QACrF,MAAM,OAAO,GAAG,4BAA4B,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAChE,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC;YACpD,WAAW;YACX,WAAW,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAChF,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAChC,yFAAyF;YACzF,yFAAyF;YACzF,GAAG,EAAE,CAAC;YACN,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,GAAG;YACrC,SAAS,EAAE,GAAG;SACf,CAAC,CAAA;QACF,OAAO,OAAO,CAAA;IAChB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CAAC,WAAmB,EAAE,GAAW,EAAE,KAAa;QACvD,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE;YAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;YAChE,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,0BAA0B,EAAE,CAAC;gBACpE,MAAM,IAAI,eAAe,CACvB,WAAW,0BAA0B,uCAAuC,EAC5E,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAC1C,CAAA;YACH,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,CAAA;YACzB,0FAA0F;YAC1F,IAAI,QAAQ,KAAK,CAAC,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAA;;gBACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;YACpC,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,GAAW;QAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YAChD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAA;YAC9D,sFAAsF;YACtF,8DAA8D;YAC9D,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAA;YACpD,OAAO,SAAS,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB;QACrC,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAA;IAC7F,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,MAAM,CAClB,WAAmB,EACnB,UAAyB,EACzB,KAAmF;QAEnF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAA;QACrD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,mBAAmB,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;YACrD,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;YACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,IAAI,CAAC,MAAM;oBAAE,OAAO,EAAE,CAAA;gBACtB,IAAI,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC;oBAAE,OAAO,EAAE,CAAA;gBAC9D,SAAQ;YACV,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;YACjC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;YACvF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACnC,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,SAAS,EAAE,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;aAC1E,CAAC,CAAC,CAAA;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CACvC;gBACE,WAAW;gBACX,WAAW,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACvE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAChC,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC5B,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,GAAG;gBACnC,SAAS,EAAE,GAAG;aACf,EACD,MAAM,EAAE,GAAG,IAAI,IAAI,CACpB,CAAA;YACD,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAA;YAC3B,uEAAuE;QACzE,CAAC;QACD,wFAAwF;QACxF,2DAA2D;QAC3D,MAAM,IAAI,aAAa,CACrB,yCAAyC,WAAW,0CAA0C,CAC/F,CAAA;IACH,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,cAAc,CAC1B,MAAyC;QAEzC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QACtB,OAAO,gCAAgC,CACrC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CACrE,CAAA;IACH,CAAC;IAED,+FAA+F;IACvF,YAAY,CAAC,MAAyC;QAC5D,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAY,CAAA;YACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAA;YACrC,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAK,EAAoC,EAAE,CAC1C,CAAC,CAAC,KAAK;gBACP,OAAO,KAAK,KAAK,QAAQ;gBACzB,OAAQ,KAAiC,CAAC,GAAG,KAAK,QAAQ,CAC7D,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/integrations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.119.0",
|
|
4
4
|
"description": "External-system integration domain logic for the Agent Architecture Board (GitHub, documents, tasks, environments, runners).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"ai": "^7.0.47",
|
|
28
28
|
"p-map": "^7.0.6",
|
|
29
29
|
"yaml": "^2.9.0",
|
|
30
|
-
"@cat-factory/contracts": "0.
|
|
31
|
-
"@cat-factory/kernel": "0.
|
|
30
|
+
"@cat-factory/contracts": "0.217.0",
|
|
31
|
+
"@cat-factory/kernel": "0.220.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"typescript": "7.0.2",
|
|
35
35
|
"undici": "^8.9.0",
|
|
36
36
|
"valibot": "^1.4.2",
|
|
37
37
|
"vitest": "^4.1.10",
|
|
38
|
-
"@cat-factory/caching": "0.13.
|
|
38
|
+
"@cat-factory/caching": "0.13.5"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsc -b tsconfig.build.json",
|