@vectros-ai/cli 0.6.4 → 0.6.5
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/CHANGELOG.md +13 -0
- package/dist/cli.js +132 -60
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +132 -60
- package/dist/cli.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -9648,6 +9648,18 @@ var codingAgentMemory = {
|
|
|
9648
9648
|
]
|
|
9649
9649
|
};
|
|
9650
9650
|
var coding_agent_memory_default = codingAgentMemory;
|
|
9651
|
+
var DATA_PLANE_ACTIONS = [
|
|
9652
|
+
"records:r",
|
|
9653
|
+
"records:c",
|
|
9654
|
+
"records:u",
|
|
9655
|
+
"search:r",
|
|
9656
|
+
"schemas:r",
|
|
9657
|
+
"inference:r",
|
|
9658
|
+
"documents:r",
|
|
9659
|
+
"documents:c",
|
|
9660
|
+
"folders:r",
|
|
9661
|
+
"folders:c"
|
|
9662
|
+
];
|
|
9651
9663
|
var agenticSdlc = {
|
|
9652
9664
|
name: "agentic-sdlc",
|
|
9653
9665
|
version: "1.0.0",
|
|
@@ -10301,23 +10313,25 @@ var agenticSdlc = {
|
|
|
10301
10313
|
]
|
|
10302
10314
|
}
|
|
10303
10315
|
],
|
|
10304
|
-
// Least-privilege, data-plane only.
|
|
10305
|
-
//
|
|
10306
|
-
//
|
|
10307
|
-
// via a status flip, so the trail of how the team's thinking evolved stays intact.
|
|
10316
|
+
// Least-privilege, data-plane only. The scope of the `ssk_*` key the bootstrap
|
|
10317
|
+
// mints for THIS blueprint's service principal (the MCP/API runtime). See
|
|
10318
|
+
// DATA_PLANE_ACTIONS above for the action set + rationale.
|
|
10308
10319
|
accessProfile: {
|
|
10309
|
-
allowedActions:
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10320
|
-
|
|
10320
|
+
allowedActions: DATA_PLANE_ACTIONS
|
|
10321
|
+
},
|
|
10322
|
+
// A reusable `editor` role for the HUMAN owner — DISTINCT from `accessProfile`
|
|
10323
|
+
// (which scopes only the service-principal key). `bootstrap` provisions this
|
|
10324
|
+
// role in the context but binds it to no one; the owner joins themselves so the
|
|
10325
|
+
// data-plane app (app.vectros.ai) shows their KB — its switcher lists only
|
|
10326
|
+
// contexts the signed-in user holds an active access profile in, and bootstrap
|
|
10327
|
+
// grants the human none by default. Bind it after bootstrap with:
|
|
10328
|
+
// vectros access grant --principal usr_<your-user-id> --context agentic-sdlc --role editor
|
|
10329
|
+
// (or the admin app's Access > Contexts > agentic-sdlc > Profiles > Create).
|
|
10330
|
+
// Editor PARITY with the service key (same DATA_PLANE_ACTIONS) so a human
|
|
10331
|
+
// curator can browse AND write/correct the KB; still no :d and no control-plane
|
|
10332
|
+
// action, so the scope gate accepts it exactly like the accessProfile.
|
|
10333
|
+
roles: {
|
|
10334
|
+
editor: [{ allowedActions: DATA_PLANE_ACTIONS }]
|
|
10321
10335
|
},
|
|
10322
10336
|
servicePrincipal: {
|
|
10323
10337
|
externalId: "agentic-sdlc",
|
|
@@ -12602,12 +12616,63 @@ function splitCsv(csv) {
|
|
|
12602
12616
|
return csv.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
12603
12617
|
}
|
|
12604
12618
|
|
|
12619
|
+
// src/paginate.ts
|
|
12620
|
+
var PAGE_LIMIT = 100;
|
|
12621
|
+
async function drainPages(fetch2) {
|
|
12622
|
+
const out = [];
|
|
12623
|
+
let startFrom;
|
|
12624
|
+
for (; ; ) {
|
|
12625
|
+
const page = await fetch2(startFrom);
|
|
12626
|
+
if (page.data) out.push(...page.data);
|
|
12627
|
+
const next = page.nextCursor;
|
|
12628
|
+
if (!next) break;
|
|
12629
|
+
startFrom = next;
|
|
12630
|
+
}
|
|
12631
|
+
return out;
|
|
12632
|
+
}
|
|
12633
|
+
|
|
12634
|
+
// src/self-principal.ts
|
|
12635
|
+
var PRINCIPAL_PREFIX_USER = "usr_";
|
|
12636
|
+
function emailFromJwt(token) {
|
|
12637
|
+
const parts = token.split(".");
|
|
12638
|
+
if (parts.length < 2) return void 0;
|
|
12639
|
+
try {
|
|
12640
|
+
const payload = Buffer.from(parts[1], "base64url").toString("utf8");
|
|
12641
|
+
const claims = JSON.parse(payload);
|
|
12642
|
+
return typeof claims.email === "string" && claims.email.trim() ? claims.email.trim() : void 0;
|
|
12643
|
+
} catch {
|
|
12644
|
+
return void 0;
|
|
12645
|
+
}
|
|
12646
|
+
}
|
|
12647
|
+
async function resolveSelfPrincipal(client, cognitoToken) {
|
|
12648
|
+
const email = emailFromJwt(cognitoToken);
|
|
12649
|
+
if (!email) return null;
|
|
12650
|
+
const target = email.toLowerCase();
|
|
12651
|
+
const users = await drainPages(
|
|
12652
|
+
(startFrom) => client.identity.listUsers(
|
|
12653
|
+
startFrom === void 0 ? { limit: PAGE_LIMIT } : { startFrom, limit: PAGE_LIMIT }
|
|
12654
|
+
)
|
|
12655
|
+
);
|
|
12656
|
+
const match = users.find(
|
|
12657
|
+
(u) => u.id && typeof u.email === "string" && u.email.toLowerCase() === target
|
|
12658
|
+
);
|
|
12659
|
+
if (!match?.id) return null;
|
|
12660
|
+
return { principalId: `${PRINCIPAL_PREFIX_USER}${match.id}`, userId: match.id, email };
|
|
12661
|
+
}
|
|
12662
|
+
|
|
12605
12663
|
// src/commands/whoami.ts
|
|
12606
12664
|
async function runWhoami(options, deps = {}) {
|
|
12607
12665
|
return withAuth(options, deps, async (auth) => {
|
|
12608
12666
|
const { identity, baseUrl } = auth;
|
|
12667
|
+
let self2 = null;
|
|
12668
|
+
try {
|
|
12669
|
+
self2 = await resolveSelfPrincipal(auth.client, auth.cognitoToken);
|
|
12670
|
+
} catch {
|
|
12671
|
+
self2 = null;
|
|
12672
|
+
}
|
|
12609
12673
|
if (options.json) {
|
|
12610
|
-
|
|
12674
|
+
const out = self2 ? { ...identity, userId: self2.userId, userPrincipalId: self2.principalId } : identity;
|
|
12675
|
+
process.stdout.write(`${formatJson(out)}
|
|
12611
12676
|
`);
|
|
12612
12677
|
return 0;
|
|
12613
12678
|
}
|
|
@@ -12619,6 +12684,7 @@ async function runWhoami(options, deps = {}) {
|
|
|
12619
12684
|
["principal", identity.principalType],
|
|
12620
12685
|
["principal id", identity.principalKeyId],
|
|
12621
12686
|
["label", identity.principalLabel],
|
|
12687
|
+
["your user id", self2?.principalId],
|
|
12622
12688
|
["allowed actions", identity.allowedActions?.length ? identity.allowedActions.join(", ") : void 0],
|
|
12623
12689
|
["token expires", expiry],
|
|
12624
12690
|
["api", baseUrl]
|
|
@@ -12628,21 +12694,6 @@ async function runWhoami(options, deps = {}) {
|
|
|
12628
12694
|
});
|
|
12629
12695
|
}
|
|
12630
12696
|
|
|
12631
|
-
// src/paginate.ts
|
|
12632
|
-
var PAGE_LIMIT = 100;
|
|
12633
|
-
async function drainPages(fetch2) {
|
|
12634
|
-
const out = [];
|
|
12635
|
-
let startFrom;
|
|
12636
|
-
for (; ; ) {
|
|
12637
|
-
const page = await fetch2(startFrom);
|
|
12638
|
-
if (page.data) out.push(...page.data);
|
|
12639
|
-
const next = page.nextCursor;
|
|
12640
|
-
if (!next) break;
|
|
12641
|
-
startFrom = next;
|
|
12642
|
-
}
|
|
12643
|
-
return out;
|
|
12644
|
-
}
|
|
12645
|
-
|
|
12646
12697
|
// src/commands/key.ts
|
|
12647
12698
|
var DEFAULT_KEY_NAME = "default";
|
|
12648
12699
|
function emitMintedKey(key, format) {
|
|
@@ -13032,6 +13083,17 @@ function assertPrincipalShape(principal) {
|
|
|
13032
13083
|
throw new Error(`--principal must be 'usr_<userId>' or 'key_<keyId>' (got '${principal}').`);
|
|
13033
13084
|
}
|
|
13034
13085
|
}
|
|
13086
|
+
var SELF_PRINCIPAL_ALIAS = "me";
|
|
13087
|
+
async function resolvePrincipalArg(raw, auth) {
|
|
13088
|
+
if (raw !== SELF_PRINCIPAL_ALIAS) return raw;
|
|
13089
|
+
const self2 = await resolveSelfPrincipal(auth.client, auth.cognitoToken);
|
|
13090
|
+
if (!self2) {
|
|
13091
|
+
throw new Error(
|
|
13092
|
+
"Could not resolve your own user id from your login. Pass --principal usr_<id> explicitly (find the id with `vectros identity list --type user`)."
|
|
13093
|
+
);
|
|
13094
|
+
}
|
|
13095
|
+
return self2.principalId;
|
|
13096
|
+
}
|
|
13035
13097
|
function renderProfile(p) {
|
|
13036
13098
|
return formatKeyValues([
|
|
13037
13099
|
["context", p.contextId],
|
|
@@ -13048,21 +13110,24 @@ async function runAccessGrant(opts, deps = {}) {
|
|
|
13048
13110
|
process.stderr.write(" \u2716 Provide exactly one of --role <roleId> or --actions <csv>.\n");
|
|
13049
13111
|
return 2;
|
|
13050
13112
|
}
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13113
|
+
if (opts.principal !== SELF_PRINCIPAL_ALIAS) {
|
|
13114
|
+
try {
|
|
13115
|
+
assertPrincipalShape(opts.principal);
|
|
13116
|
+
} catch (err) {
|
|
13117
|
+
process.stderr.write(` \u2716 ${formatError(err)}
|
|
13055
13118
|
`);
|
|
13056
|
-
|
|
13119
|
+
return 2;
|
|
13120
|
+
}
|
|
13057
13121
|
}
|
|
13058
13122
|
return withAuth(opts, deps, async (auth) => {
|
|
13059
13123
|
const client = auth.client;
|
|
13060
13124
|
try {
|
|
13125
|
+
const principal = await resolvePrincipalArg(opts.principal, auth);
|
|
13061
13126
|
const scopes = hasActions ? [{ allowed_actions: splitCsv(opts.actions) }] : void 0;
|
|
13062
13127
|
const profile = await client.auth.createAccessProfile({
|
|
13063
13128
|
contextId: opts.context,
|
|
13064
13129
|
body: {
|
|
13065
|
-
principalId:
|
|
13130
|
+
principalId: principal,
|
|
13066
13131
|
roleId: opts.role,
|
|
13067
13132
|
scopes
|
|
13068
13133
|
}
|
|
@@ -13074,7 +13139,7 @@ async function runAccessGrant(opts, deps = {}) {
|
|
|
13074
13139
|
}
|
|
13075
13140
|
process.stdout.write(
|
|
13076
13141
|
`
|
|
13077
|
-
\u2714 Granted ${
|
|
13142
|
+
\u2714 Granted ${principal} in '${opts.context}'` + (hasRole ? ` via role '${opts.role}'` : ` with ${splitCsv(opts.actions).length} action(s)`) + `
|
|
13078
13143
|
${renderProfile(profile)}
|
|
13079
13144
|
`
|
|
13080
13145
|
);
|
|
@@ -13087,18 +13152,21 @@ ${renderProfile(profile)}
|
|
|
13087
13152
|
});
|
|
13088
13153
|
}
|
|
13089
13154
|
async function runAccessRevoke(opts, deps = {}) {
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13155
|
+
if (opts.principal !== SELF_PRINCIPAL_ALIAS) {
|
|
13156
|
+
try {
|
|
13157
|
+
assertPrincipalShape(opts.principal);
|
|
13158
|
+
} catch (err) {
|
|
13159
|
+
process.stderr.write(` \u2716 ${formatError(err)}
|
|
13094
13160
|
`);
|
|
13095
|
-
|
|
13161
|
+
return 2;
|
|
13162
|
+
}
|
|
13096
13163
|
}
|
|
13097
13164
|
return withAuth(opts, deps, async (auth) => {
|
|
13098
13165
|
const client = auth.client;
|
|
13099
13166
|
try {
|
|
13100
|
-
|
|
13101
|
-
|
|
13167
|
+
const principal = await resolvePrincipalArg(opts.principal, auth);
|
|
13168
|
+
await client.auth.deleteAccessProfile({ contextId: opts.context, principalId: principal });
|
|
13169
|
+
process.stdout.write(` \u2714 Revoked ${principal} from '${opts.context}'
|
|
13102
13170
|
`);
|
|
13103
13171
|
return 0;
|
|
13104
13172
|
} catch (err) {
|
|
@@ -13113,7 +13181,7 @@ async function runAccessList(opts, deps = {}) {
|
|
|
13113
13181
|
process.stderr.write(" \u2716 Provide exactly one of --context <c> or --principal <p>.\n");
|
|
13114
13182
|
return 2;
|
|
13115
13183
|
}
|
|
13116
|
-
if (opts.principal) {
|
|
13184
|
+
if (opts.principal && opts.principal !== SELF_PRINCIPAL_ALIAS) {
|
|
13117
13185
|
try {
|
|
13118
13186
|
assertPrincipalShape(opts.principal);
|
|
13119
13187
|
} catch (err) {
|
|
@@ -13125,10 +13193,11 @@ async function runAccessList(opts, deps = {}) {
|
|
|
13125
13193
|
return withAuth(opts, deps, async (auth) => {
|
|
13126
13194
|
const client = auth.client;
|
|
13127
13195
|
try {
|
|
13196
|
+
const principal = opts.principal ? await resolvePrincipalArg(opts.principal, auth) : void 0;
|
|
13128
13197
|
const rows = opts.context ? await drainPages(
|
|
13129
13198
|
(startFrom) => client.auth.listAccessProfiles({ contextId: opts.context, startFrom, limit: PAGE_LIMIT })
|
|
13130
13199
|
) : await drainPages(
|
|
13131
|
-
(startFrom) => client.auth.listProfilesForPrincipal({ principalId:
|
|
13200
|
+
(startFrom) => client.auth.listProfilesForPrincipal({ principalId: principal, startFrom, limit: PAGE_LIMIT })
|
|
13132
13201
|
);
|
|
13133
13202
|
if (opts.json) {
|
|
13134
13203
|
process.stdout.write(`${formatJson(rows)}
|
|
@@ -13152,17 +13221,20 @@ async function runAccessList(opts, deps = {}) {
|
|
|
13152
13221
|
});
|
|
13153
13222
|
}
|
|
13154
13223
|
async function runAccessGet(opts, deps = {}) {
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13224
|
+
if (opts.principal !== SELF_PRINCIPAL_ALIAS) {
|
|
13225
|
+
try {
|
|
13226
|
+
assertPrincipalShape(opts.principal);
|
|
13227
|
+
} catch (err) {
|
|
13228
|
+
process.stderr.write(` \u2716 ${formatError(err)}
|
|
13159
13229
|
`);
|
|
13160
|
-
|
|
13230
|
+
return 2;
|
|
13231
|
+
}
|
|
13161
13232
|
}
|
|
13162
13233
|
return withAuth(opts, deps, async (auth) => {
|
|
13163
13234
|
const client = auth.client;
|
|
13164
13235
|
try {
|
|
13165
|
-
const
|
|
13236
|
+
const principal = await resolvePrincipalArg(opts.principal, auth);
|
|
13237
|
+
const p = await client.auth.getAccessProfile({ contextId: opts.context, principalId: principal });
|
|
13166
13238
|
if (opts.json) {
|
|
13167
13239
|
process.stdout.write(`${formatJson(p)}
|
|
13168
13240
|
`);
|
|
@@ -13938,9 +14010,9 @@ async function runBlueprintTest(fileOrName, opts, deps = {}) {
|
|
|
13938
14010
|
|
|
13939
14011
|
// src/build-info.ts
|
|
13940
14012
|
var BUILD_INFO = {
|
|
13941
|
-
cli: true ? "0.6.
|
|
14013
|
+
cli: true ? "0.6.5" : "dev",
|
|
13942
14014
|
sdk: true ? "0.31.0" : "dev",
|
|
13943
|
-
blueprints: true ? "0.6.
|
|
14015
|
+
blueprints: true ? "0.6.3" : "dev"
|
|
13944
14016
|
};
|
|
13945
14017
|
function formatBuildInfo() {
|
|
13946
14018
|
return `vectros ${BUILD_INFO.cli} (sdk ${BUILD_INFO.sdk}, blueprints ${BUILD_INFO.blueprints})`;
|
|
@@ -14059,7 +14131,7 @@ function registerRoleCommands(program, deps) {
|
|
|
14059
14131
|
}
|
|
14060
14132
|
function registerAccessCommands(program, deps) {
|
|
14061
14133
|
const access2 = program.command("access").description("Manage access bindings: principal \u2194 context \u2194 role/scopes.");
|
|
14062
|
-
const grant = access2.command("grant").description("Bind a principal to a context via a role or inline actions.").requiredOption("--principal <p>", "principal: 'usr_<userId>'
|
|
14134
|
+
const grant = access2.command("grant").description("Bind a principal to a context via a role or inline actions.").requiredOption("--principal <p>", "principal: 'usr_<userId>', 'key_<keyId>', or 'me' (your own user)").requiredOption("--context <c>", "app context").option("--role <roleId>", "reference a Role (XOR --actions)").option("--actions <csv>", "inline single-clause actions, comma-separated (XOR --role)");
|
|
14063
14135
|
addCommonAuthOptions(grant).action(
|
|
14064
14136
|
async (flags) => {
|
|
14065
14137
|
process.exit(
|
|
@@ -14073,15 +14145,15 @@ function registerAccessCommands(program, deps) {
|
|
|
14073
14145
|
);
|
|
14074
14146
|
}
|
|
14075
14147
|
);
|
|
14076
|
-
const revoke = access2.command("revoke").description("Remove a principal\u2019s binding in a context.").requiredOption("--principal <p>", "principal: 'usr_<userId>'
|
|
14148
|
+
const revoke = access2.command("revoke").description("Remove a principal\u2019s binding in a context.").requiredOption("--principal <p>", "principal: 'usr_<userId>', 'key_<keyId>', or 'me' (your own user)").requiredOption("--context <c>", "app context");
|
|
14077
14149
|
addAuthOptions(revoke).action(async (flags) => {
|
|
14078
14150
|
process.exit(await runAccessRevoke({ ...toCommonOptions(flags), principal: flags.principal, context: flags.context }, deps));
|
|
14079
14151
|
});
|
|
14080
|
-
const list = access2.command("list").description("List a context\u2019s members (--context) or a principal\u2019s contexts (--principal).").option("--context <c>", "list members of this context").option("--principal <p>", "list contexts this principal is bound to");
|
|
14152
|
+
const list = access2.command("list").description("List a context\u2019s members (--context) or a principal\u2019s contexts (--principal).").option("--context <c>", "list members of this context").option("--principal <p>", "list contexts this principal is bound to ('me' = your own user)");
|
|
14081
14153
|
addCommonAuthOptions(list).action(async (flags) => {
|
|
14082
14154
|
process.exit(await runAccessList({ ...toCommonOptions(flags), context: flags.context, principal: flags.principal }, deps));
|
|
14083
14155
|
});
|
|
14084
|
-
const get = access2.command("get").description("Show one principal\u2019s binding in a context.").requiredOption("--principal <p>", "principal: 'usr_<userId>'
|
|
14156
|
+
const get = access2.command("get").description("Show one principal\u2019s binding in a context.").requiredOption("--principal <p>", "principal: 'usr_<userId>', 'key_<keyId>', or 'me' (your own user)").requiredOption("--context <c>", "app context");
|
|
14085
14157
|
addCommonAuthOptions(get).action(async (flags) => {
|
|
14086
14158
|
process.exit(await runAccessGet({ ...toCommonOptions(flags), principal: flags.principal, context: flags.context }, deps));
|
|
14087
14159
|
});
|