@topolo/sdk 0.21.2 → 0.21.3
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/index.cjs +246 -171
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +246 -171
- package/dist/node/credential-store.cjs +133 -74
- package/dist/node/credential-store.d.cts +51 -1
- package/dist/node/credential-store.d.ts +51 -1
- package/dist/node/credential-store.js +130 -72
- package/package.json +2 -2
|
@@ -29,6 +29,7 @@ __export(credential_store_exports, {
|
|
|
29
29
|
configPath: () => configPath,
|
|
30
30
|
contextKey: () => contextKey,
|
|
31
31
|
createPlatformInstallationSecretBackend: () => createPlatformInstallationSecretBackend,
|
|
32
|
+
createProtectedActionSecretStore: () => createProtectedActionSecretStore,
|
|
32
33
|
credentialSourceFromConfig: () => credentialSourceFromConfig,
|
|
33
34
|
deleteExternalAgentInstallation: () => deleteExternalAgentInstallation,
|
|
34
35
|
envVarPrefix: () => envVarPrefix,
|
|
@@ -55,7 +56,7 @@ module.exports = __toCommonJS(credential_store_exports);
|
|
|
55
56
|
var import_promises2 = require("fs/promises");
|
|
56
57
|
var import_node_fs2 = require("fs");
|
|
57
58
|
var import_node_os2 = require("os");
|
|
58
|
-
var
|
|
59
|
+
var import_node_path3 = require("path");
|
|
59
60
|
|
|
60
61
|
// src/errors.ts
|
|
61
62
|
var TopoloSdkError = class extends Error {
|
|
@@ -411,68 +412,12 @@ var TopoloOAuth = class {
|
|
|
411
412
|
}
|
|
412
413
|
};
|
|
413
414
|
|
|
414
|
-
// src/
|
|
415
|
-
var
|
|
416
|
-
var
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
},
|
|
421
|
-
staging: {
|
|
422
|
-
auth: "https://auth.stg.topolo.us",
|
|
423
|
-
developers: "https://developers.stg.topolo.us"
|
|
424
|
-
},
|
|
425
|
-
development: {
|
|
426
|
-
auth: "https://auth.topolo.dev",
|
|
427
|
-
developers: "https://developers.topolo.dev"
|
|
428
|
-
},
|
|
429
|
-
local: {}
|
|
430
|
-
};
|
|
431
|
-
function hostnameHasSuffix(hostname, suffix) {
|
|
432
|
-
return hostname === suffix || hostname.endsWith(`.${suffix}`);
|
|
433
|
-
}
|
|
434
|
-
function workersDevAccountMatches(hostname, account) {
|
|
435
|
-
if (!hostname.endsWith(".workers.dev")) return false;
|
|
436
|
-
const labels = hostname.slice(0, -".workers.dev".length).split(".");
|
|
437
|
-
return labels.length >= 2 && labels.at(-1) === account;
|
|
438
|
-
}
|
|
439
|
-
function originMatchesEnvironment(url, environment) {
|
|
440
|
-
const hostname = url.hostname.toLowerCase();
|
|
441
|
-
if (environment === "local") {
|
|
442
|
-
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
443
|
-
}
|
|
444
|
-
if (url.protocol !== "https:") return false;
|
|
445
|
-
if (environment === "production") {
|
|
446
|
-
return hostnameHasSuffix(hostname, "topolo.app") || hostnameHasSuffix(hostname, "topolo.io") || hostname === "api.ol0.me" || workersDevAccountMatches(hostname, "topolo");
|
|
447
|
-
}
|
|
448
|
-
if (environment === "staging") {
|
|
449
|
-
return hostnameHasSuffix(hostname, "stg.topolo.us") || workersDevAccountMatches(hostname, "topolo-staging");
|
|
450
|
-
}
|
|
451
|
-
return hostnameHasSuffix(hostname, "topolo.dev") || workersDevAccountMatches(hostname, "topolo-development");
|
|
452
|
-
}
|
|
453
|
-
function assertTopoloServiceUrlEnvironment(service, value, environment) {
|
|
454
|
-
let url;
|
|
455
|
-
try {
|
|
456
|
-
url = new URL(value);
|
|
457
|
-
} catch {
|
|
458
|
-
throw new TopoloSdkError("invalid_service_url", `Invalid URL configured for Topolo service "${service}".`);
|
|
459
|
-
}
|
|
460
|
-
if (url.protocol !== "https:" && url.protocol !== "http:" || url.username || url.password || !originMatchesEnvironment(url, environment)) {
|
|
461
|
-
throw new TopoloSdkError(
|
|
462
|
-
"environment_mismatch",
|
|
463
|
-
`Refusing Topolo service "${service}": ${url.origin} does not belong to ${environment}.`
|
|
464
|
-
);
|
|
465
|
-
}
|
|
466
|
-
return url.origin;
|
|
467
|
-
}
|
|
468
|
-
function topoloServiceOrigins(serviceUrls, environment) {
|
|
469
|
-
return Object.fromEntries(
|
|
470
|
-
Object.entries(serviceUrls ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(([service, value]) => [
|
|
471
|
-
service,
|
|
472
|
-
assertTopoloServiceUrlEnvironment(service, value, environment)
|
|
473
|
-
])
|
|
474
|
-
);
|
|
475
|
-
}
|
|
415
|
+
// src/node/action-secret-store.ts
|
|
416
|
+
var import_node_crypto = require("crypto");
|
|
417
|
+
var import_node_path2 = require("path");
|
|
418
|
+
|
|
419
|
+
// src/action-secrets.ts
|
|
420
|
+
var ACTION_SECRET_PREFIX = "topolo-secret:";
|
|
476
421
|
|
|
477
422
|
// src/node/installation-store.ts
|
|
478
423
|
var import_node_child_process = require("child_process");
|
|
@@ -522,6 +467,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
522
467
|
const platform2 = options.platform ?? (0, import_node_os.platform)();
|
|
523
468
|
const spawn = options.spawn ?? ((command, args, spawnOptions) => (0, import_node_child_process.spawnSync)(command, args, spawnOptions));
|
|
524
469
|
const root = options.root ?? installationStorePath();
|
|
470
|
+
const service = options.service ?? KEYCHAIN_SERVICE;
|
|
525
471
|
if (platform2 === "darwin") {
|
|
526
472
|
const write = (account, value) => runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
|
|
527
473
|
input: `${value}
|
|
@@ -530,7 +476,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
530
476
|
env: {
|
|
531
477
|
...process.env,
|
|
532
478
|
TOPOLO_KEYCHAIN_ACCOUNT: account,
|
|
533
|
-
TOPOLO_KEYCHAIN_SERVICE:
|
|
479
|
+
TOPOLO_KEYCHAIN_SERVICE: service
|
|
534
480
|
}
|
|
535
481
|
}), "macOS Keychain write");
|
|
536
482
|
const read = (account) => {
|
|
@@ -539,7 +485,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
539
485
|
"-a",
|
|
540
486
|
account,
|
|
541
487
|
"-s",
|
|
542
|
-
|
|
488
|
+
service,
|
|
543
489
|
"-w"
|
|
544
490
|
], { encoding: "utf8" });
|
|
545
491
|
if (result.status === 44) return null;
|
|
@@ -551,7 +497,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
551
497
|
"-a",
|
|
552
498
|
account,
|
|
553
499
|
"-s",
|
|
554
|
-
|
|
500
|
+
service
|
|
555
501
|
], { encoding: "utf8" });
|
|
556
502
|
if (result.status !== 44) runOrThrow(result, "macOS Keychain delete");
|
|
557
503
|
};
|
|
@@ -598,9 +544,9 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
598
544
|
async set(account, value) {
|
|
599
545
|
runOrThrow(spawn("secret-tool", [
|
|
600
546
|
"store",
|
|
601
|
-
"--label=Topolo
|
|
547
|
+
"--label=Topolo protected credential",
|
|
602
548
|
"service",
|
|
603
|
-
|
|
549
|
+
service,
|
|
604
550
|
"account",
|
|
605
551
|
account
|
|
606
552
|
], { input: value, encoding: "utf8" }), "Linux Secret Service write");
|
|
@@ -609,7 +555,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
609
555
|
const result = spawn("secret-tool", [
|
|
610
556
|
"lookup",
|
|
611
557
|
"service",
|
|
612
|
-
|
|
558
|
+
service,
|
|
613
559
|
"account",
|
|
614
560
|
account
|
|
615
561
|
], { encoding: "utf8" });
|
|
@@ -620,7 +566,7 @@ function createPlatformInstallationSecretBackend(options = {}) {
|
|
|
620
566
|
const result = spawn("secret-tool", [
|
|
621
567
|
"clear",
|
|
622
568
|
"service",
|
|
623
|
-
|
|
569
|
+
service,
|
|
624
570
|
"account",
|
|
625
571
|
account
|
|
626
572
|
], { encoding: "utf8" });
|
|
@@ -691,6 +637,118 @@ async function deleteExternalAgentInstallation(environment, id, backend = create
|
|
|
691
637
|
await (0, import_promises.rm)(installationPath(environment, id), { force: true });
|
|
692
638
|
}
|
|
693
639
|
|
|
640
|
+
// src/node/action-secret-store.ts
|
|
641
|
+
function createProtectedActionSecretStore(options) {
|
|
642
|
+
const backend = options.backend ?? createPlatformInstallationSecretBackend({
|
|
643
|
+
service: "topolo-action-handoff",
|
|
644
|
+
root: (0, import_node_path2.join)(installationStorePath(), "action-handoff")
|
|
645
|
+
});
|
|
646
|
+
const now = options.now ?? Date.now;
|
|
647
|
+
async function account(reference) {
|
|
648
|
+
if (!/^topolo-secret:[0-9a-f-]{36}$/.test(reference)) throw new TopoloSdkError("invalid_action_secret_reference", "Invalid protected action reference.");
|
|
649
|
+
const identity = await options.identity();
|
|
650
|
+
if (!identity.user.id) throw new TopoloSdkError("action_secret_identity_required", "A verified identity is required for protected action handoff.");
|
|
651
|
+
if (identity.kind === "api_key" && !identity.apiKey?.id) throw new TopoloSdkError("action_secret_identity_required", "A verified API key identity is required for protected action handoff.");
|
|
652
|
+
const scope = (0, import_node_crypto.createHash)("sha256").update(JSON.stringify([
|
|
653
|
+
options.environment,
|
|
654
|
+
identity.user.principalId ?? identity.user.id,
|
|
655
|
+
identity.organization?.id ?? null,
|
|
656
|
+
identity.apiKey?.id ?? null
|
|
657
|
+
])).digest("hex");
|
|
658
|
+
return `${scope}-${reference.slice(ACTION_SECRET_PREFIX.length)}`;
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
async save(value) {
|
|
662
|
+
const reference = `${ACTION_SECRET_PREFIX}${(0, import_node_crypto.randomUUID)()}`;
|
|
663
|
+
await backend.set(await account(reference), JSON.stringify({ value, expiresAt: now() + 30 * 60 * 1e3 }));
|
|
664
|
+
return reference;
|
|
665
|
+
},
|
|
666
|
+
async load(reference) {
|
|
667
|
+
const key = await account(reference);
|
|
668
|
+
const encoded = await backend.get(key);
|
|
669
|
+
if (!encoded) throw new TopoloSdkError("action_secret_unavailable", "Protected action reference is missing or belongs to another identity or environment.");
|
|
670
|
+
let record;
|
|
671
|
+
try {
|
|
672
|
+
record = JSON.parse(encoded);
|
|
673
|
+
} catch {
|
|
674
|
+
throw new TopoloSdkError("action_secret_invalid", "Protected action reference is corrupt.");
|
|
675
|
+
}
|
|
676
|
+
if (!Number.isFinite(record?.expiresAt) || !Object.hasOwn(record, "value")) throw new TopoloSdkError("action_secret_invalid", "Protected action reference is corrupt.");
|
|
677
|
+
if (record.expiresAt <= now()) {
|
|
678
|
+
await backend.delete(key);
|
|
679
|
+
throw new TopoloSdkError("action_secret_expired", "Protected action reference expired. Repeat the originating action if its contract permits.");
|
|
680
|
+
}
|
|
681
|
+
return record.value;
|
|
682
|
+
},
|
|
683
|
+
async delete(reference) {
|
|
684
|
+
await backend.delete(await account(reference));
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
// src/environment.ts
|
|
690
|
+
var TOPOLO_RUNTIME_ENVIRONMENTS = ["production", "staging", "development", "local"];
|
|
691
|
+
var TOPOLO_ENVIRONMENT_SERVICE_URLS = {
|
|
692
|
+
production: {
|
|
693
|
+
auth: "https://auth.topolo.app",
|
|
694
|
+
developers: "https://developers.topolo.app"
|
|
695
|
+
},
|
|
696
|
+
staging: {
|
|
697
|
+
auth: "https://auth.stg.topolo.us",
|
|
698
|
+
developers: "https://developers.stg.topolo.us"
|
|
699
|
+
},
|
|
700
|
+
development: {
|
|
701
|
+
auth: "https://auth.topolo.dev",
|
|
702
|
+
developers: "https://developers.topolo.dev"
|
|
703
|
+
},
|
|
704
|
+
local: {}
|
|
705
|
+
};
|
|
706
|
+
function hostnameHasSuffix(hostname, suffix) {
|
|
707
|
+
return hostname === suffix || hostname.endsWith(`.${suffix}`);
|
|
708
|
+
}
|
|
709
|
+
function workersDevAccountMatches(hostname, account) {
|
|
710
|
+
if (!hostname.endsWith(".workers.dev")) return false;
|
|
711
|
+
const labels = hostname.slice(0, -".workers.dev".length).split(".");
|
|
712
|
+
return labels.length >= 2 && labels.at(-1) === account;
|
|
713
|
+
}
|
|
714
|
+
function originMatchesEnvironment(url, environment) {
|
|
715
|
+
const hostname = url.hostname.toLowerCase();
|
|
716
|
+
if (environment === "local") {
|
|
717
|
+
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
718
|
+
}
|
|
719
|
+
if (url.protocol !== "https:") return false;
|
|
720
|
+
if (environment === "production") {
|
|
721
|
+
return hostnameHasSuffix(hostname, "topolo.app") || hostnameHasSuffix(hostname, "topolo.io") || hostname === "api.ol0.me" || workersDevAccountMatches(hostname, "topolo");
|
|
722
|
+
}
|
|
723
|
+
if (environment === "staging") {
|
|
724
|
+
return hostnameHasSuffix(hostname, "stg.topolo.us") || workersDevAccountMatches(hostname, "topolo-staging");
|
|
725
|
+
}
|
|
726
|
+
return hostnameHasSuffix(hostname, "topolo.dev") || workersDevAccountMatches(hostname, "topolo-development");
|
|
727
|
+
}
|
|
728
|
+
function assertTopoloServiceUrlEnvironment(service, value, environment) {
|
|
729
|
+
let url;
|
|
730
|
+
try {
|
|
731
|
+
url = new URL(value);
|
|
732
|
+
} catch {
|
|
733
|
+
throw new TopoloSdkError("invalid_service_url", `Invalid URL configured for Topolo service "${service}".`);
|
|
734
|
+
}
|
|
735
|
+
if (url.protocol !== "https:" && url.protocol !== "http:" || url.username || url.password || !originMatchesEnvironment(url, environment)) {
|
|
736
|
+
throw new TopoloSdkError(
|
|
737
|
+
"environment_mismatch",
|
|
738
|
+
`Refusing Topolo service "${service}": ${url.origin} does not belong to ${environment}.`
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
return url.origin;
|
|
742
|
+
}
|
|
743
|
+
function topoloServiceOrigins(serviceUrls, environment) {
|
|
744
|
+
return Object.fromEntries(
|
|
745
|
+
Object.entries(serviceUrls ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(([service, value]) => [
|
|
746
|
+
service,
|
|
747
|
+
assertTopoloServiceUrlEnvironment(service, value, environment)
|
|
748
|
+
])
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
|
|
694
752
|
// src/node/credential-store.ts
|
|
695
753
|
var TOPOLO_ENVIRONMENTS = TOPOLO_RUNTIME_ENVIRONMENTS;
|
|
696
754
|
function contextKey(contextType, organizationId) {
|
|
@@ -700,8 +758,8 @@ var ENVIRONMENT_DEFAULT_SERVICE_URLS = TOPOLO_ENVIRONMENT_SERVICE_URLS;
|
|
|
700
758
|
function configPath() {
|
|
701
759
|
const override = process.env.TOPOLO_CONFIG_PATH;
|
|
702
760
|
if (override) return override;
|
|
703
|
-
const base = process.env.XDG_CONFIG_HOME || ((0, import_node_os2.platform)() === "win32" ? (0,
|
|
704
|
-
return (0,
|
|
761
|
+
const base = process.env.XDG_CONFIG_HOME || ((0, import_node_os2.platform)() === "win32" ? (0, import_node_path3.join)((0, import_node_os2.homedir)(), "AppData", "Roaming") : (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".config"));
|
|
762
|
+
return (0, import_node_path3.join)(base, "topolo", "config.json");
|
|
705
763
|
}
|
|
706
764
|
async function readConfig() {
|
|
707
765
|
const path = configPath();
|
|
@@ -715,7 +773,7 @@ async function readConfig() {
|
|
|
715
773
|
}
|
|
716
774
|
async function writeConfig(config) {
|
|
717
775
|
const path = configPath();
|
|
718
|
-
await (0, import_promises2.mkdir)((0,
|
|
776
|
+
await (0, import_promises2.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
|
|
719
777
|
await (0, import_promises2.writeFile)(path, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
720
778
|
if ((0, import_node_os2.platform)() !== "win32") {
|
|
721
779
|
try {
|
|
@@ -835,7 +893,7 @@ var CONFIG_LOCK_TIMEOUT_MS = 5e3;
|
|
|
835
893
|
var CONFIG_LOCK_STALE_MS = 12e4;
|
|
836
894
|
async function withConfigWriteLock(operation) {
|
|
837
895
|
const lockPath = `${configPath()}.lock`;
|
|
838
|
-
await (0, import_promises2.mkdir)((0,
|
|
896
|
+
await (0, import_promises2.mkdir)((0, import_node_path3.dirname)(lockPath), { recursive: true });
|
|
839
897
|
const startedAt = Date.now();
|
|
840
898
|
while (true) {
|
|
841
899
|
try {
|
|
@@ -1012,6 +1070,7 @@ function resolvedProfileConfig(config, environment = selectedEnvironment()) {
|
|
|
1012
1070
|
configPath,
|
|
1013
1071
|
contextKey,
|
|
1014
1072
|
createPlatformInstallationSecretBackend,
|
|
1073
|
+
createProtectedActionSecretStore,
|
|
1015
1074
|
credentialSourceFromConfig,
|
|
1016
1075
|
deleteExternalAgentInstallation,
|
|
1017
1076
|
envVarPrefix,
|
|
@@ -26,11 +26,53 @@ type TopoloCredential = {
|
|
|
26
26
|
expiresAt?: number;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
interface TopoloActionSecretStore {
|
|
30
|
+
save(value: unknown): Promise<string>;
|
|
31
|
+
load(reference: string): Promise<unknown>;
|
|
32
|
+
delete(reference: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
declare const TOPOLO_RUNTIME_ENVIRONMENTS: readonly ["production", "staging", "development", "local"];
|
|
30
36
|
type TopoloRuntimeEnvironment = (typeof TOPOLO_RUNTIME_ENVIRONMENTS)[number];
|
|
31
37
|
declare function assertTopoloServiceUrlEnvironment(service: string, value: string, environment: TopoloRuntimeEnvironment): string;
|
|
32
38
|
declare function topoloServiceOrigins(serviceUrls: Record<string, string> | undefined, environment: TopoloRuntimeEnvironment): Record<string, string>;
|
|
33
39
|
|
|
40
|
+
interface CredentialIntrospection {
|
|
41
|
+
kind: 'api_key' | 'access_token';
|
|
42
|
+
authorizationMode: 'context_rbac' | 'oauth_scopes' | 'session_rbac' | 'api_key' | 'unknown';
|
|
43
|
+
user: {
|
|
44
|
+
id: string;
|
|
45
|
+
email: string;
|
|
46
|
+
name: string | null;
|
|
47
|
+
role: string;
|
|
48
|
+
permissions: string[];
|
|
49
|
+
principalId?: string | null;
|
|
50
|
+
principalType?: 'agent_employee' | 'external_agent' | null;
|
|
51
|
+
accountableUserId?: string | null;
|
|
52
|
+
agentInstanceId?: string | null;
|
|
53
|
+
installationId?: string | null;
|
|
54
|
+
provider?: string | null;
|
|
55
|
+
model?: string | null;
|
|
56
|
+
serviceScopes?: string[];
|
|
57
|
+
policyRef?: string | null;
|
|
58
|
+
};
|
|
59
|
+
organization: {
|
|
60
|
+
id: string;
|
|
61
|
+
slug: string;
|
|
62
|
+
name: string;
|
|
63
|
+
} | null;
|
|
64
|
+
apiKey: {
|
|
65
|
+
id: string | null;
|
|
66
|
+
name: string | null;
|
|
67
|
+
appId: string | null;
|
|
68
|
+
scopes: string[];
|
|
69
|
+
resourceBindings: Array<{
|
|
70
|
+
resourceType: string;
|
|
71
|
+
resourceId: string;
|
|
72
|
+
}>;
|
|
73
|
+
} | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
34
76
|
interface ExternalAgentInstallation {
|
|
35
77
|
id: string;
|
|
36
78
|
environment: TopoloRuntimeEnvironment;
|
|
@@ -64,6 +106,7 @@ declare function createPlatformInstallationSecretBackend(options?: {
|
|
|
64
106
|
platform?: NodeJS.Platform;
|
|
65
107
|
spawn?: Spawn;
|
|
66
108
|
root?: string;
|
|
109
|
+
service?: string;
|
|
67
110
|
}): InstallationSecretBackend;
|
|
68
111
|
declare function writeExternalAgentInstallation(installation: ExternalAgentInstallation, secret: ExternalAgentInstallationSecret, backend?: InstallationSecretBackend): Promise<void>;
|
|
69
112
|
declare function readExternalAgentInstallation(environment: TopoloRuntimeEnvironment, id: string, backend?: InstallationSecretBackend): Promise<{
|
|
@@ -73,6 +116,13 @@ declare function readExternalAgentInstallation(environment: TopoloRuntimeEnviron
|
|
|
73
116
|
declare function listExternalAgentInstallations(environment: TopoloRuntimeEnvironment): Promise<ExternalAgentInstallation[]>;
|
|
74
117
|
declare function deleteExternalAgentInstallation(environment: TopoloRuntimeEnvironment, id: string, backend?: InstallationSecretBackend): Promise<void>;
|
|
75
118
|
|
|
119
|
+
declare function createProtectedActionSecretStore(options: {
|
|
120
|
+
environment: TopoloRuntimeEnvironment;
|
|
121
|
+
identity: () => Promise<CredentialIntrospection>;
|
|
122
|
+
backend?: InstallationSecretBackend;
|
|
123
|
+
now?: () => number;
|
|
124
|
+
}): TopoloActionSecretStore;
|
|
125
|
+
|
|
76
126
|
/**
|
|
77
127
|
* Node-only credential store shared by the `topolo` CLI and `@topolo/mcp`.
|
|
78
128
|
*
|
|
@@ -166,4 +216,4 @@ declare function resolveServiceUrls(configUrls?: Record<string, string>, environ
|
|
|
166
216
|
declare function assertServiceUrlForEnvironment(service: string, serviceUrl: string | undefined, environment?: TopoloEnvironment): void;
|
|
167
217
|
declare function resolvedProfileConfig(config: TopoloConfig, environment?: TopoloEnvironment): TopoloEnvironmentProfile;
|
|
168
218
|
|
|
169
|
-
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, type ExternalAgentInstallation, type ExternalAgentInstallationSecret, type InstallationSecretBackend, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, assertServiceUrlForEnvironment, assertTopoloServiceUrlEnvironment, clearProfileCredential, configPath, contextKey, createPlatformInstallationSecretBackend, credentialSourceFromConfig, deleteExternalAgentInstallation, envVarPrefix, installationStorePath, listExternalAgentInstallations, normalizeEnvironment, profileForEnvironment, readConfig, readExternalAgentInstallation, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, topoloServiceOrigins, writeConfig, writeContextCredential, writeExternalAgentInstallation, writeProfileConfig };
|
|
219
|
+
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, type ExternalAgentInstallation, type ExternalAgentInstallationSecret, type InstallationSecretBackend, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, assertServiceUrlForEnvironment, assertTopoloServiceUrlEnvironment, clearProfileCredential, configPath, contextKey, createPlatformInstallationSecretBackend, createProtectedActionSecretStore, credentialSourceFromConfig, deleteExternalAgentInstallation, envVarPrefix, installationStorePath, listExternalAgentInstallations, normalizeEnvironment, profileForEnvironment, readConfig, readExternalAgentInstallation, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, topoloServiceOrigins, writeConfig, writeContextCredential, writeExternalAgentInstallation, writeProfileConfig };
|
|
@@ -26,11 +26,53 @@ type TopoloCredential = {
|
|
|
26
26
|
expiresAt?: number;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
interface TopoloActionSecretStore {
|
|
30
|
+
save(value: unknown): Promise<string>;
|
|
31
|
+
load(reference: string): Promise<unknown>;
|
|
32
|
+
delete(reference: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
declare const TOPOLO_RUNTIME_ENVIRONMENTS: readonly ["production", "staging", "development", "local"];
|
|
30
36
|
type TopoloRuntimeEnvironment = (typeof TOPOLO_RUNTIME_ENVIRONMENTS)[number];
|
|
31
37
|
declare function assertTopoloServiceUrlEnvironment(service: string, value: string, environment: TopoloRuntimeEnvironment): string;
|
|
32
38
|
declare function topoloServiceOrigins(serviceUrls: Record<string, string> | undefined, environment: TopoloRuntimeEnvironment): Record<string, string>;
|
|
33
39
|
|
|
40
|
+
interface CredentialIntrospection {
|
|
41
|
+
kind: 'api_key' | 'access_token';
|
|
42
|
+
authorizationMode: 'context_rbac' | 'oauth_scopes' | 'session_rbac' | 'api_key' | 'unknown';
|
|
43
|
+
user: {
|
|
44
|
+
id: string;
|
|
45
|
+
email: string;
|
|
46
|
+
name: string | null;
|
|
47
|
+
role: string;
|
|
48
|
+
permissions: string[];
|
|
49
|
+
principalId?: string | null;
|
|
50
|
+
principalType?: 'agent_employee' | 'external_agent' | null;
|
|
51
|
+
accountableUserId?: string | null;
|
|
52
|
+
agentInstanceId?: string | null;
|
|
53
|
+
installationId?: string | null;
|
|
54
|
+
provider?: string | null;
|
|
55
|
+
model?: string | null;
|
|
56
|
+
serviceScopes?: string[];
|
|
57
|
+
policyRef?: string | null;
|
|
58
|
+
};
|
|
59
|
+
organization: {
|
|
60
|
+
id: string;
|
|
61
|
+
slug: string;
|
|
62
|
+
name: string;
|
|
63
|
+
} | null;
|
|
64
|
+
apiKey: {
|
|
65
|
+
id: string | null;
|
|
66
|
+
name: string | null;
|
|
67
|
+
appId: string | null;
|
|
68
|
+
scopes: string[];
|
|
69
|
+
resourceBindings: Array<{
|
|
70
|
+
resourceType: string;
|
|
71
|
+
resourceId: string;
|
|
72
|
+
}>;
|
|
73
|
+
} | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
34
76
|
interface ExternalAgentInstallation {
|
|
35
77
|
id: string;
|
|
36
78
|
environment: TopoloRuntimeEnvironment;
|
|
@@ -64,6 +106,7 @@ declare function createPlatformInstallationSecretBackend(options?: {
|
|
|
64
106
|
platform?: NodeJS.Platform;
|
|
65
107
|
spawn?: Spawn;
|
|
66
108
|
root?: string;
|
|
109
|
+
service?: string;
|
|
67
110
|
}): InstallationSecretBackend;
|
|
68
111
|
declare function writeExternalAgentInstallation(installation: ExternalAgentInstallation, secret: ExternalAgentInstallationSecret, backend?: InstallationSecretBackend): Promise<void>;
|
|
69
112
|
declare function readExternalAgentInstallation(environment: TopoloRuntimeEnvironment, id: string, backend?: InstallationSecretBackend): Promise<{
|
|
@@ -73,6 +116,13 @@ declare function readExternalAgentInstallation(environment: TopoloRuntimeEnviron
|
|
|
73
116
|
declare function listExternalAgentInstallations(environment: TopoloRuntimeEnvironment): Promise<ExternalAgentInstallation[]>;
|
|
74
117
|
declare function deleteExternalAgentInstallation(environment: TopoloRuntimeEnvironment, id: string, backend?: InstallationSecretBackend): Promise<void>;
|
|
75
118
|
|
|
119
|
+
declare function createProtectedActionSecretStore(options: {
|
|
120
|
+
environment: TopoloRuntimeEnvironment;
|
|
121
|
+
identity: () => Promise<CredentialIntrospection>;
|
|
122
|
+
backend?: InstallationSecretBackend;
|
|
123
|
+
now?: () => number;
|
|
124
|
+
}): TopoloActionSecretStore;
|
|
125
|
+
|
|
76
126
|
/**
|
|
77
127
|
* Node-only credential store shared by the `topolo` CLI and `@topolo/mcp`.
|
|
78
128
|
*
|
|
@@ -166,4 +216,4 @@ declare function resolveServiceUrls(configUrls?: Record<string, string>, environ
|
|
|
166
216
|
declare function assertServiceUrlForEnvironment(service: string, serviceUrl: string | undefined, environment?: TopoloEnvironment): void;
|
|
167
217
|
declare function resolvedProfileConfig(config: TopoloConfig, environment?: TopoloEnvironment): TopoloEnvironmentProfile;
|
|
168
218
|
|
|
169
|
-
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, type ExternalAgentInstallation, type ExternalAgentInstallationSecret, type InstallationSecretBackend, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, assertServiceUrlForEnvironment, assertTopoloServiceUrlEnvironment, clearProfileCredential, configPath, contextKey, createPlatformInstallationSecretBackend, credentialSourceFromConfig, deleteExternalAgentInstallation, envVarPrefix, installationStorePath, listExternalAgentInstallations, normalizeEnvironment, profileForEnvironment, readConfig, readExternalAgentInstallation, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, topoloServiceOrigins, writeConfig, writeContextCredential, writeExternalAgentInstallation, writeProfileConfig };
|
|
219
|
+
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, type ExternalAgentInstallation, type ExternalAgentInstallationSecret, type InstallationSecretBackend, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, assertServiceUrlForEnvironment, assertTopoloServiceUrlEnvironment, clearProfileCredential, configPath, contextKey, createPlatformInstallationSecretBackend, createProtectedActionSecretStore, credentialSourceFromConfig, deleteExternalAgentInstallation, envVarPrefix, installationStorePath, listExternalAgentInstallations, normalizeEnvironment, profileForEnvironment, readConfig, readExternalAgentInstallation, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, topoloServiceOrigins, writeConfig, writeContextCredential, writeExternalAgentInstallation, writeProfileConfig };
|