@vectros-ai/cli 0.10.0 → 0.12.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/AUTHORING.md +7 -0
- package/CHANGELOG.md +41 -0
- package/dist/cli.js +176 -47
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +176 -47
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -3
package/AUTHORING.md
CHANGED
|
@@ -244,6 +244,13 @@ principal's `externalId`, the per-machine key name, and each seed record's
|
|
|
244
244
|
`externalId`. Bump `version` when you evolve a blueprint. (Note: schema
|
|
245
245
|
`typeName` is immutable after first apply.)
|
|
246
246
|
|
|
247
|
+
**Pair `:r` with every `:c` you request.** Being handed back an existing item
|
|
248
|
+
on a re-apply collision is a read of that item, not part of create authority —
|
|
249
|
+
so a `records:c`-only `accessProfile.allowedActions` converges on first apply
|
|
250
|
+
but fails on every re-apply with an "already exists" error instead of the
|
|
251
|
+
existing record. Request `:r` alongside `:c` on every resource your blueprint
|
|
252
|
+
creates (the bundled blueprints all do this — see the example above).
|
|
253
|
+
|
|
247
254
|
## Distribution
|
|
248
255
|
|
|
249
256
|
- **Bundled** — reviewed, versioned blueprints shipped in the library
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,47 @@
|
|
|
3
3
|
All notable changes to `@vectros-ai/cli` are documented here.
|
|
4
4
|
This project adheres to [Semantic Versioning](https://semver.org).
|
|
5
5
|
|
|
6
|
+
## 0.12.0
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **Blueprints can declare `basedOn` on a schema.** A blueprint schema may now set
|
|
11
|
+
`basedOn: <schemaId>` to mark itself as a customization of an existing same-named
|
|
12
|
+
schema in the context; the loader forwards it to `createSchema`. Previously a
|
|
13
|
+
blueprint declaring `basedOn` would fail blueprint validation outright (an
|
|
14
|
+
unrecognized field); now it's accepted and forwarded. No bundled blueprint uses
|
|
15
|
+
this yet — it's forward-looking plumbing for a blueprint author (or a re-apply
|
|
16
|
+
into a context that already has a same-named hand-authored schema) who would
|
|
17
|
+
otherwise hit a `400` with no escape.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Dependency maintenance** — repinned the bundled `@vectros-ai/sdk` to `0.37.0`
|
|
22
|
+
(additive `basedOn` schema customization, `specificityRank` on namespaces, and
|
|
23
|
+
search/RAG response fields) and the bundled `@vectros-ai/blueprints` to `0.9.0`.
|
|
24
|
+
The CLI bundles both into its published binary, so this is a rebuild against
|
|
25
|
+
their current versions.
|
|
26
|
+
|
|
27
|
+
## 0.11.0
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **`access explain` no longer previews access that the platform denies.** A clause keyed on an
|
|
32
|
+
unrecognized ownership dimension — a retired `orgId`/`clientId`, or an invalid
|
|
33
|
+
`scope:<namespace>` — now shows as granting nothing, matching how the server evaluates it,
|
|
34
|
+
instead of appearing to grant records the credential cannot actually reach. The dead clause is
|
|
35
|
+
shown explicitly rather than silently dropped.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **Clearer errors for expired sessions and rate limits.** When a command fails because your
|
|
40
|
+
login has expired, the CLI now tells you to run `vectros login` and retry; a rate-limited
|
|
41
|
+
request tells you to wait and retry. Failures that carry a typed error code surface it on the
|
|
42
|
+
support line alongside the request id.
|
|
43
|
+
- **`bootstrap` warns when seeded sample data could not be indexed.** If a seed record or document
|
|
44
|
+
is stored but not (fully) searchable, the run summary now says so — and why — instead of
|
|
45
|
+
reporting it as fully seeded.
|
|
46
|
+
|
|
6
47
|
## 0.10.0
|
|
7
48
|
|
|
8
49
|
### Changed (breaking)
|
package/dist/cli.js
CHANGED
|
@@ -1649,6 +1649,7 @@ __export(api_exports, {
|
|
|
1649
1649
|
FileUploadRequest: () => FileUploadRequest,
|
|
1650
1650
|
ForbiddenError: () => ForbiddenError,
|
|
1651
1651
|
IdentityLookupRequest: () => IdentityLookupRequest,
|
|
1652
|
+
IndexFailure: () => IndexFailure,
|
|
1652
1653
|
InternalServerError: () => InternalServerError,
|
|
1653
1654
|
ListEntitiesRequestOrder: () => ListEntitiesRequestOrder,
|
|
1654
1655
|
ListUsersRequestOrder: () => ListUsersRequestOrder,
|
|
@@ -2170,6 +2171,17 @@ var IdentityLookupRequest;
|
|
|
2170
2171
|
Desc: "desc"
|
|
2171
2172
|
};
|
|
2172
2173
|
})(IdentityLookupRequest || (IdentityLookupRequest = {}));
|
|
2174
|
+
var IndexFailure;
|
|
2175
|
+
((IndexFailure2) => {
|
|
2176
|
+
IndexFailure2.Code = {
|
|
2177
|
+
SourceUnavailable: "SOURCE_UNAVAILABLE",
|
|
2178
|
+
TextIndexFailed: "TEXT_INDEX_FAILED",
|
|
2179
|
+
EmbeddingFailed: "EMBEDDING_FAILED",
|
|
2180
|
+
IndexingFailed: "INDEXING_FAILED",
|
|
2181
|
+
VectorLimitExceeded: "VECTOR_LIMIT_EXCEEDED",
|
|
2182
|
+
Internal: "INTERNAL"
|
|
2183
|
+
};
|
|
2184
|
+
})(IndexFailure || (IndexFailure = {}));
|
|
2173
2185
|
var ModelDataVersionResponse;
|
|
2174
2186
|
((ModelDataVersionResponse2) => {
|
|
2175
2187
|
ModelDataVersionResponse2.ChangeType = {
|
|
@@ -5686,7 +5698,7 @@ var AuthClient = class {
|
|
|
5686
5698
|
);
|
|
5687
5699
|
}
|
|
5688
5700
|
/**
|
|
5689
|
-
* Creates a short-lived JWT bearer token restricted to specific actions and, optionally, to a particular user
|
|
5701
|
+
* Creates a short-lived JWT bearer token restricted to specific actions and, optionally, to a particular user or identity entity (in any namespace). Use this to hand a narrowly-scoped credential to a browser or downstream service so it never sees your root API key. Only callable with a root API key (`sk_*`).
|
|
5690
5702
|
*
|
|
5691
5703
|
* @param {Vectros.TokenRequest} request
|
|
5692
5704
|
* @param {AuthClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -5903,7 +5915,7 @@ var ComplianceClient = class {
|
|
|
5903
5915
|
this._options = normalizeClientOptionsWithAuth(options);
|
|
5904
5916
|
}
|
|
5905
5917
|
/**
|
|
5906
|
-
* Submits a right-to-erasure request for a single end-subject (a user,
|
|
5918
|
+
* Submits a right-to-erasure request for a single end-subject (a user, or an identity entity in any namespace). Erasure removes exactly the data the subject solely owns across the declared contexts, plus the subject's identity and lookup rows. It never touches another account's data and never cascades into another subject's data. The request is asynchronous: it returns 202 with a `requestId`; poll `GET /v1/erasure-requests/{id}` until the job completes to obtain the completion certificate. Requires a root API key — a scoped credential is rejected with 403.
|
|
5907
5919
|
*
|
|
5908
5920
|
* @param {Vectros.ErasureRequest} request
|
|
5909
5921
|
* @param {ComplianceClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6212,7 +6224,7 @@ var DocumentsClient = class {
|
|
|
6212
6224
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents");
|
|
6213
6225
|
}
|
|
6214
6226
|
/**
|
|
6215
|
-
* Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope.
|
|
6227
|
+
* Creates a document from a raw text string and queues it for asynchronous indexing so it becomes searchable. Optionally supply an `externalId` to make the create idempotent — if a document with the same `externalId` already exists in your context, that existing document is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing document was returned) tells the two apart. To overwrite an existing document's content instead of returning it unchanged, set `?upsert=true` (this also requires the `documents:u` scope). Requires the `documents:c` scope to create. Being returned the existing document on a collision is a read of that document's data and additionally requires the `documents:r` scope — a credential holding `documents:c` alone receives a `400` ("already exists") on collision instead of the document.
|
|
6216
6228
|
*
|
|
6217
6229
|
* @param {Vectros.IngestDocumentRequest} request
|
|
6218
6230
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -6538,25 +6550,29 @@ var DocumentsClient = class {
|
|
|
6538
6550
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PATCH", "/v1/documents/{id}");
|
|
6539
6551
|
}
|
|
6540
6552
|
/**
|
|
6541
|
-
* Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
|
|
6553
|
+
* Finds documents of a given type by field value. Supported fields: `externalId` (the document's first-class external identifier — no schema declaration required) and any field declared as a lookup field on the bound schema. A lookup on a sensitive field is rejected here because the value would appear in the URL query string; use POST /v1/documents/lookup (the request-body variant) for a sensitive field instead. `type`'s schema resolves with basedOn-aware shadowing: your own `userId`- or `scope`-owned variant if you have one, otherwise the shared base — for a scoped credential the owner is always your own token identity; `userId`/`scope` here only apply as an explicit owner selector for a root API key. Results are paginated: set `limit` for the page size and feed the returned `nextCursor` back as `startFrom` to fetch the next page. The response is a `{data, nextCursor}` envelope. Requires the `documents:r` scope.
|
|
6542
6554
|
*
|
|
6543
6555
|
* @param {Vectros.LookupDocumentsRequest} request
|
|
6544
6556
|
* @param {DocumentsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
6545
6557
|
*
|
|
6558
|
+
* @throws {@link Vectros.BadRequestError}
|
|
6559
|
+
*
|
|
6546
6560
|
* @example
|
|
6547
6561
|
* await client.documents.lookupDocuments({
|
|
6548
6562
|
* type: "invoice",
|
|
6549
6563
|
* field: "po_number",
|
|
6550
6564
|
* value: "PO-1001",
|
|
6551
6565
|
* prefix: "PO-2024",
|
|
6552
|
-
* startFrom: "550e8400-e29b-41d4-a716-446655440000"
|
|
6566
|
+
* startFrom: "550e8400-e29b-41d4-a716-446655440000",
|
|
6567
|
+
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
6568
|
+
* scope: "org:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
|
6553
6569
|
* })
|
|
6554
6570
|
*/
|
|
6555
6571
|
lookupDocuments(request, requestOptions) {
|
|
6556
6572
|
return HttpResponsePromise.fromPromise(this.__lookupDocuments(request, requestOptions));
|
|
6557
6573
|
}
|
|
6558
6574
|
async __lookupDocuments(request, requestOptions) {
|
|
6559
|
-
const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order } = request;
|
|
6575
|
+
const { type: type_, field, value, from: from_, to, prefix, startFrom, limit, order, userId, scope } = request;
|
|
6560
6576
|
const _queryParams = {
|
|
6561
6577
|
type: type_,
|
|
6562
6578
|
field,
|
|
@@ -6566,7 +6582,9 @@ var DocumentsClient = class {
|
|
|
6566
6582
|
prefix,
|
|
6567
6583
|
startFrom,
|
|
6568
6584
|
limit,
|
|
6569
|
-
order: order != null ? order : void 0
|
|
6585
|
+
order: order != null ? order : void 0,
|
|
6586
|
+
userId,
|
|
6587
|
+
scope
|
|
6570
6588
|
};
|
|
6571
6589
|
const _authRequest = await this._options.authProvider.getAuthRequest();
|
|
6572
6590
|
const _headers = mergeHeaders(
|
|
@@ -6592,11 +6610,16 @@ var DocumentsClient = class {
|
|
|
6592
6610
|
return { data: _response.body, rawResponse: _response.rawResponse };
|
|
6593
6611
|
}
|
|
6594
6612
|
if (_response.error.reason === "status-code") {
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6613
|
+
switch (_response.error.statusCode) {
|
|
6614
|
+
case 400:
|
|
6615
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
6616
|
+
default:
|
|
6617
|
+
throw new VectrosError({
|
|
6618
|
+
statusCode: _response.error.statusCode,
|
|
6619
|
+
body: _response.error.body,
|
|
6620
|
+
rawResponse: _response.rawResponse
|
|
6621
|
+
});
|
|
6622
|
+
}
|
|
6600
6623
|
}
|
|
6601
6624
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/documents/lookup");
|
|
6602
6625
|
}
|
|
@@ -6964,7 +6987,7 @@ var FoldersClient = class {
|
|
|
6964
6987
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/folders");
|
|
6965
6988
|
}
|
|
6966
6989
|
/**
|
|
6967
|
-
* Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope.
|
|
6990
|
+
* Creates a folder to organize your documents and records. If `parentFolderId` is omitted, the folder is created under your context's default root folder. Folder creation is idempotent by (slug + parent): if a folder with the same slug already exists under the same parent, that existing folder is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing folder was returned) tells the two apart. To overwrite an existing folder's mutable fields instead of returning it unchanged, set `?upsert=true` (this also requires the `folders:u` scope). Requires the `folders:c` scope to create. Being returned the existing folder on a collision is a read of that folder's data and additionally requires the `folders:r` scope — a credential holding `folders:c` alone receives a `400` ("already exists") on collision instead of the folder.
|
|
6968
6991
|
*
|
|
6969
6992
|
* @param {Vectros.CreateFolderRequest} request
|
|
6970
6993
|
* @param {FoldersClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7422,7 +7445,7 @@ var IdentityClient = class {
|
|
|
7422
7445
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/entities/{namespace}");
|
|
7423
7446
|
}
|
|
7424
7447
|
/**
|
|
7425
|
-
* Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope.
|
|
7448
|
+
* Creates a new entity in the given namespace. This call is idempotent on `externalId` within the namespace: if an entity with the same `externalId` already exists, the existing record is returned instead of creating a duplicate (`created: false`, HTTP 200). To overwrite an existing entity's content instead of returning it unchanged, set `?upsert=true` (also requires the `entities:u:<namespace>` scope). The namespace must be entity-backed (`org`/`client`, or registered via `POST /v1/namespaces`). Requires the `entities:c:<namespace>` scope to create. Being returned the existing entity on a collision is a read of that entity's data and additionally requires the `entities:r:<namespace>` scope — a credential holding `entities:c:<namespace>` alone receives a `400` ("already in use") on collision instead of the entity.
|
|
7426
7449
|
*
|
|
7427
7450
|
* @param {Vectros.CreateEntityRequest} request
|
|
7428
7451
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7866,7 +7889,7 @@ var IdentityClient = class {
|
|
|
7866
7889
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces/{namespace}");
|
|
7867
7890
|
}
|
|
7868
7891
|
/**
|
|
7869
|
-
* Updates the mutable fields (`entityBacked`, `defaultSchemaId`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
|
|
7892
|
+
* Updates the mutable fields (`entityBacked`, `defaultSchemaId`, `specificityRank`) of a registered namespace. The namespace name itself is immutable. Requires a root API key. The reserved built-ins cannot be updated.
|
|
7870
7893
|
*
|
|
7871
7894
|
* @param {Vectros.UpdateNamespaceRequest} request
|
|
7872
7895
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -7879,7 +7902,8 @@ var IdentityClient = class {
|
|
|
7879
7902
|
* await client.identity.updateNamespace({
|
|
7880
7903
|
* namespace: "team",
|
|
7881
7904
|
* body: {
|
|
7882
|
-
* namespace: "team"
|
|
7905
|
+
* namespace: "team",
|
|
7906
|
+
* specificityRank: 1500
|
|
7883
7907
|
* }
|
|
7884
7908
|
* })
|
|
7885
7909
|
*/
|
|
@@ -8044,7 +8068,7 @@ var IdentityClient = class {
|
|
|
8044
8068
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/namespaces");
|
|
8045
8069
|
}
|
|
8046
8070
|
/**
|
|
8047
|
-
* Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
|
|
8071
|
+
* Registers a new scope namespace and declares whether its values resolve to identity entities (`entityBacked`). Also requires `specificityRank`, an explicit, account-unique position in the specificity order used to break recordType schema-resolution ties. Requires a root API key. The reserved names `org` and `client` are built in and cannot be registered.
|
|
8048
8072
|
*
|
|
8049
8073
|
* @param {Vectros.NamespaceRequest} request
|
|
8050
8074
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -8055,7 +8079,8 @@ var IdentityClient = class {
|
|
|
8055
8079
|
*
|
|
8056
8080
|
* @example
|
|
8057
8081
|
* await client.identity.registerNamespace({
|
|
8058
|
-
* namespace: "team"
|
|
8082
|
+
* namespace: "team",
|
|
8083
|
+
* specificityRank: 1500
|
|
8059
8084
|
* })
|
|
8060
8085
|
*/
|
|
8061
8086
|
registerNamespace(request, requestOptions) {
|
|
@@ -8172,7 +8197,7 @@ var IdentityClient = class {
|
|
|
8172
8197
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/users");
|
|
8173
8198
|
}
|
|
8174
8199
|
/**
|
|
8175
|
-
* Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope.
|
|
8200
|
+
* Creates a user identity in your account. The operation is idempotent on `externalId`: if a user with the same `externalId` already exists, the existing record is returned instead of creating a duplicate. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing user was returned) tells the two apart. To overwrite an existing user's mutable fields (email, status, payload, schema binding) instead of returning it unchanged, set `?upsert=true` (this also requires the `users:u` scope). Requires the `users:c` scope to create. Being returned the existing user on a collision is a read of that user's data and additionally requires the `users:r` scope — a credential holding `users:c` alone receives a `400` ("already exists") on collision instead of the user.
|
|
8176
8201
|
*
|
|
8177
8202
|
* @param {Vectros.CreateUserRequest} request
|
|
8178
8203
|
* @param {IdentityClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -9043,7 +9068,7 @@ var RecordsClient = class {
|
|
|
9043
9068
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/records");
|
|
9044
9069
|
}
|
|
9045
9070
|
/**
|
|
9046
|
-
* Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope.
|
|
9071
|
+
* Creates a new record of a given type. The `payload` is validated against that type's schema before the record is stored. Identify the type by sending `typeName`, `schemaId`, or both (they must agree); if you send only `schemaId`, the type is taken from that schema. Optionally supply an `externalId` to make the create idempotent — if a record with the same `externalId` already exists in your context, that existing record is returned unchanged instead of a duplicate being created. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing record was returned) tells the two apart. To overwrite an existing record's content instead of returning it unchanged, set `?upsert=true` (this also requires the `records:u:<type>` scope). Requires the `records:c:<type>` scope to create. Being returned the existing record on a collision is a read of that record's data and additionally requires the `records:r:<type>` scope — a credential holding `records:c:<type>` alone receives a `400` ("already exists") on collision instead of the record.
|
|
9047
9072
|
*
|
|
9048
9073
|
* @param {Vectros.CreateRecordRequest} request
|
|
9049
9074
|
* @param {RecordsClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -9634,6 +9659,8 @@ var SchemasClient = class {
|
|
|
9634
9659
|
* @param {Vectros.ListSchemasRequest} request
|
|
9635
9660
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
9636
9661
|
*
|
|
9662
|
+
* @throws {@link Vectros.BadRequestError}
|
|
9663
|
+
*
|
|
9637
9664
|
* @example
|
|
9638
9665
|
* await client.schemas.listSchemas({
|
|
9639
9666
|
* userId: "550e8400-e29b-41d4-a716-446655440000",
|
|
@@ -9680,16 +9707,21 @@ var SchemasClient = class {
|
|
|
9680
9707
|
return { data: _response.body, rawResponse: _response.rawResponse };
|
|
9681
9708
|
}
|
|
9682
9709
|
if (_response.error.reason === "status-code") {
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9710
|
+
switch (_response.error.statusCode) {
|
|
9711
|
+
case 400:
|
|
9712
|
+
throw new BadRequestError(_response.error.body, _response.rawResponse);
|
|
9713
|
+
default:
|
|
9714
|
+
throw new VectrosError({
|
|
9715
|
+
statusCode: _response.error.statusCode,
|
|
9716
|
+
body: _response.error.body,
|
|
9717
|
+
rawResponse: _response.rawResponse
|
|
9718
|
+
});
|
|
9719
|
+
}
|
|
9688
9720
|
}
|
|
9689
9721
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas");
|
|
9690
9722
|
}
|
|
9691
9723
|
/**
|
|
9692
|
-
* Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:
|
|
9724
|
+
* Defines a new record type with optional field definitions, validation rules, and lookup indexes. Idempotent by `typeName` within the same ownership scope: re-creating an existing `typeName` returns the existing schema rather than failing. The response's `created` field (and the HTTP status — 201 when created, 200 when an existing schema was returned) tells the two apart. To reconcile an existing schema to the submitted shape instead of returning it unchanged, set `?upsert=true` (this also requires the `schemas:u` scope; only legal schema changes are applied — migration-locked changes are rejected). Requires the `schemas:c` scope to create. Being returned the existing schema on a collision is a read of that schema's data and additionally requires the `schemas:r` scope — a credential holding `schemas:c` alone receives a `400` ("already in use") on collision instead of the schema.
|
|
9693
9725
|
*
|
|
9694
9726
|
* @param {Vectros.CreateSchemaRequest} request
|
|
9695
9727
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -9833,7 +9865,7 @@ var SchemasClient = class {
|
|
|
9833
9865
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/v1/schemas/{id}");
|
|
9834
9866
|
}
|
|
9835
9867
|
/**
|
|
9836
|
-
* Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:
|
|
9868
|
+
* Updates a record schema. Fields you omit are preserved; `typeName` is immutable and cannot be changed. Collection fields (`fields`, `lookupFields`, `renderHints`, `capabilities`) are replaced in full when supplied. Requires the `schemas:u` scope.
|
|
9837
9869
|
*
|
|
9838
9870
|
* @param {Vectros.UpdateSchemaRequest} request
|
|
9839
9871
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -9902,7 +9934,7 @@ var SchemasClient = class {
|
|
|
9902
9934
|
return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/v1/schemas/{id}");
|
|
9903
9935
|
}
|
|
9904
9936
|
/**
|
|
9905
|
-
* Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. Requires the `schemas:
|
|
9937
|
+
* Permanently deletes a record schema. The request is refused with 409 if records of this type still exist — delete those records first, since every record must reference a live schema. A lineage base (a schema other schemas declare `basedOn`) also cannot be deleted while any such variant still exists — delete the variant schema(s) first. Requires the `schemas:d` scope.
|
|
9906
9938
|
*
|
|
9907
9939
|
* @param {Vectros.DeleteSchemaRequest} request
|
|
9908
9940
|
* @param {SchemasClient.RequestOptions} requestOptions - Request-specific configuration.
|
|
@@ -10299,7 +10331,14 @@ var BlueprintSchemaSchema = import_zod.z.object({
|
|
|
10299
10331
|
// With a scoped token these must be consistent with the profile's dataScope
|
|
10300
10332
|
// (a cross-consistency lint is deferred to the lint slice).
|
|
10301
10333
|
userId: import_zod.z.string().min(1).optional(),
|
|
10302
|
-
scopes: import_zod.z.array(import_zod.z.string().min(1)).max(2).optional()
|
|
10334
|
+
scopes: import_zod.z.array(import_zod.z.string().min(1)).max(2).optional(),
|
|
10335
|
+
// The id of an existing schema this one is a CUSTOMIZATION of, when a schema
|
|
10336
|
+
// named `typeName` already exists in this context — required in that case,
|
|
10337
|
+
// and must be omitted when this create is the first schema under that name
|
|
10338
|
+
// (it becomes that name's shared base). Must point directly at the base (one
|
|
10339
|
+
// hop); immutable once set. Mirrors the `basedOn` field on the platform's
|
|
10340
|
+
// schema-create request.
|
|
10341
|
+
basedOn: import_zod.z.string().min(1).optional()
|
|
10303
10342
|
}).strict();
|
|
10304
10343
|
var BlueprintAccessProfileSchema = import_zod.z.object({
|
|
10305
10344
|
// Validated structurally here; the SCOPE GATE (in @vectros-ai/cli) is
|
|
@@ -12480,19 +12519,21 @@ function extractServerError(err) {
|
|
|
12480
12519
|
const statusCode = typeof e.statusCode === "number" ? e.statusCode : void 0;
|
|
12481
12520
|
let serverMessage;
|
|
12482
12521
|
let requestId;
|
|
12522
|
+
let errorCode;
|
|
12483
12523
|
if (e.body && typeof e.body === "object") {
|
|
12484
12524
|
const b = e.body;
|
|
12485
12525
|
if (typeof b.message === "string" && b.message.trim()) serverMessage = b.message.trim();
|
|
12486
12526
|
if (typeof b.requestId === "string" && b.requestId.trim()) requestId = b.requestId.trim();
|
|
12527
|
+
if (typeof b.errorCode === "string" && b.errorCode.trim()) errorCode = b.errorCode.trim();
|
|
12487
12528
|
} else if (typeof e.body === "string" && e.body.trim()) {
|
|
12488
12529
|
serverMessage = e.body.trim();
|
|
12489
12530
|
}
|
|
12490
|
-
if (serverMessage) return { statusCode, message: serverMessage, requestId };
|
|
12531
|
+
if (serverMessage) return { statusCode, message: serverMessage, requestId, errorCode };
|
|
12491
12532
|
const message = typeof e.message === "string" ? e.message : "";
|
|
12492
12533
|
const isSdkEnvelope = /\nStatus code:/.test(message);
|
|
12493
|
-
if (message && !isSdkEnvelope) return { statusCode, message, requestId };
|
|
12494
|
-
if (statusCode) return { statusCode, message: `HTTP ${statusCode}`, requestId };
|
|
12495
|
-
if (message) return { statusCode, message, requestId };
|
|
12534
|
+
if (message && !isSdkEnvelope) return { statusCode, message, requestId, errorCode };
|
|
12535
|
+
if (statusCode) return { statusCode, message: `HTTP ${statusCode}`, requestId, errorCode };
|
|
12536
|
+
if (message) return { statusCode, message, requestId, errorCode };
|
|
12496
12537
|
}
|
|
12497
12538
|
return { message: String(err) };
|
|
12498
12539
|
}
|
|
@@ -12503,15 +12544,17 @@ async function devRouteError(res, action) {
|
|
|
12503
12544
|
const raw = await res.text().catch(() => "");
|
|
12504
12545
|
let message;
|
|
12505
12546
|
let requestId;
|
|
12547
|
+
let errorCode;
|
|
12506
12548
|
try {
|
|
12507
12549
|
const parsed = JSON.parse(raw);
|
|
12508
12550
|
if (typeof parsed.message === "string" && parsed.message.trim()) message = parsed.message.trim();
|
|
12509
12551
|
if (typeof parsed.requestId === "string" && parsed.requestId.trim()) requestId = parsed.requestId.trim();
|
|
12552
|
+
if (typeof parsed.errorCode === "string" && parsed.errorCode.trim()) errorCode = parsed.errorCode.trim();
|
|
12510
12553
|
} catch {
|
|
12511
12554
|
}
|
|
12512
12555
|
const err = new Error(`${action}: HTTP ${res.status}`);
|
|
12513
12556
|
err.statusCode = res.status;
|
|
12514
|
-
err.body = { message: message ?? `HTTP ${res.status}`, requestId };
|
|
12557
|
+
err.body = { message: message ?? `HTTP ${res.status}`, requestId, errorCode };
|
|
12515
12558
|
return err;
|
|
12516
12559
|
}
|
|
12517
12560
|
function formatCliError(err, opts) {
|
|
@@ -12520,14 +12563,28 @@ function formatCliError(err, opts) {
|
|
|
12520
12563
|
const block = actionable ?? ` \u2716 ${opts.action}: ${info.message}
|
|
12521
12564
|
`;
|
|
12522
12565
|
const debug = opts.debug ?? Boolean(process.env.VECTROS_MCP_DEBUG);
|
|
12523
|
-
if (debug && info.requestId) {
|
|
12524
|
-
|
|
12566
|
+
if (debug && (info.requestId || info.errorCode)) {
|
|
12567
|
+
const parts = [
|
|
12568
|
+
info.errorCode ? `errorCode: ${info.errorCode}` : null,
|
|
12569
|
+
info.requestId ? `requestId: ${info.requestId}` : null
|
|
12570
|
+
].filter(Boolean);
|
|
12571
|
+
return `${block} (${parts.join(", ")} \u2014 quote this to support)
|
|
12525
12572
|
`;
|
|
12526
12573
|
}
|
|
12527
12574
|
return block;
|
|
12528
12575
|
}
|
|
12529
12576
|
function renderActionableError(info) {
|
|
12530
12577
|
const msg = info.message;
|
|
12578
|
+
switch (info.errorCode) {
|
|
12579
|
+
case "SESSION_REFRESH_REQUIRED":
|
|
12580
|
+
return ` \u2716 Your session has expired.
|
|
12581
|
+
Run 'vectros login' to re-authenticate, then retry.
|
|
12582
|
+
`;
|
|
12583
|
+
case "RATE_LIMITED":
|
|
12584
|
+
return ` \u2716 ${msg}
|
|
12585
|
+
You're being rate-limited \u2014 wait a moment and retry.
|
|
12586
|
+
`;
|
|
12587
|
+
}
|
|
12531
12588
|
if (/scoped-key limit reached/i.test(msg)) {
|
|
12532
12589
|
const plan = /plan '([^']+)'/i.exec(msg)?.[1];
|
|
12533
12590
|
const count = /\((\d+) active keys\)/i.exec(msg)?.[1];
|
|
@@ -13076,8 +13133,13 @@ var KNOWN_CONTROL_PLANE_RESOURCES = [
|
|
|
13076
13133
|
"users",
|
|
13077
13134
|
"billing",
|
|
13078
13135
|
"admin",
|
|
13079
|
-
|
|
13080
|
-
|
|
13136
|
+
// Identity/compartment provisioning. The flat `orgs`/`clients` resources were
|
|
13137
|
+
// folded into the generic `entities` (per-namespace) + `namespaces` surfaces,
|
|
13138
|
+
// which is what the API now scopes on — so those are the current spellings a
|
|
13139
|
+
// pack could name. (Cosmetic: any non-data-plane resource hard-rejects whether
|
|
13140
|
+
// or not it is listed here; this list only sharpens the error message.)
|
|
13141
|
+
"entities",
|
|
13142
|
+
"namespaces"
|
|
13081
13143
|
];
|
|
13082
13144
|
var VALID_OPS = /* @__PURE__ */ new Set(["c", "r", "u", "d"]);
|
|
13083
13145
|
var DATA_PLANE_SET = new Set(DATA_PLANE_ALLOWLIST);
|
|
@@ -13434,7 +13496,8 @@ async function runLoader(client, input) {
|
|
|
13434
13496
|
capabilities: toCapabilities(s.capabilities),
|
|
13435
13497
|
active: s.active,
|
|
13436
13498
|
userId: s.userId,
|
|
13437
|
-
scopes: s.scopes
|
|
13499
|
+
scopes: s.scopes,
|
|
13500
|
+
basedOn: s.basedOn
|
|
13438
13501
|
};
|
|
13439
13502
|
const resp = await ctxClient.schemas.createSchema({ upsert: true, body: schemaBody });
|
|
13440
13503
|
if (resp.id) schemaIds[s.typeName] = resp.id;
|
|
@@ -13524,6 +13587,21 @@ async function runLoader(client, input) {
|
|
|
13524
13587
|
let seededCount = 0;
|
|
13525
13588
|
const seededRecordIds = [];
|
|
13526
13589
|
const seededDocumentIds = [];
|
|
13590
|
+
const seedIndexFailures = [];
|
|
13591
|
+
const noteIfIndexFailed = (created, rec, surface) => {
|
|
13592
|
+
if (created.indexStatus !== "FAILED") return;
|
|
13593
|
+
seedIndexFailures.push({
|
|
13594
|
+
externalId: rec.externalId,
|
|
13595
|
+
typeName: rec.typeName,
|
|
13596
|
+
surface,
|
|
13597
|
+
code: created.indexFailure?.code,
|
|
13598
|
+
message: created.indexFailure?.message
|
|
13599
|
+
});
|
|
13600
|
+
log.warn(
|
|
13601
|
+
{ component: "loader", typeName: rec.typeName, externalId: rec.externalId, code: created.indexFailure?.code },
|
|
13602
|
+
"seed stored but failed to index"
|
|
13603
|
+
);
|
|
13604
|
+
};
|
|
13527
13605
|
for (const rec of skipSeed ? [] : blueprint.seed ?? []) {
|
|
13528
13606
|
const schemaId = schemaIds[rec.typeName];
|
|
13529
13607
|
if (!schemaId) {
|
|
@@ -13544,6 +13622,7 @@ async function runLoader(client, input) {
|
|
|
13544
13622
|
}
|
|
13545
13623
|
});
|
|
13546
13624
|
if (created.id) seededDocumentIds.push(created.id);
|
|
13625
|
+
noteIfIndexFailed(created, rec, "document");
|
|
13547
13626
|
} else {
|
|
13548
13627
|
const created = await ctxClient.records.createRecord({
|
|
13549
13628
|
body: {
|
|
@@ -13555,6 +13634,7 @@ async function runLoader(client, input) {
|
|
|
13555
13634
|
}
|
|
13556
13635
|
});
|
|
13557
13636
|
if (created.id) seededRecordIds.push(created.id);
|
|
13637
|
+
noteIfIndexFailed(created, rec, "record");
|
|
13558
13638
|
}
|
|
13559
13639
|
seededCount++;
|
|
13560
13640
|
}
|
|
@@ -13573,7 +13653,8 @@ async function runLoader(client, input) {
|
|
|
13573
13653
|
roleIds,
|
|
13574
13654
|
seededCount,
|
|
13575
13655
|
seededRecordIds,
|
|
13576
|
-
seededDocumentIds
|
|
13656
|
+
seededDocumentIds,
|
|
13657
|
+
seedIndexFailures
|
|
13577
13658
|
};
|
|
13578
13659
|
}
|
|
13579
13660
|
function buildPlan(blueprint, opts = {}) {
|
|
@@ -13828,6 +13909,17 @@ function seedSummaryLine(opts) {
|
|
|
13828
13909
|
return opts.seededCount ? ` \u2714 Seeded ${opts.seededCount} record(s)
|
|
13829
13910
|
` : "";
|
|
13830
13911
|
}
|
|
13912
|
+
function seedIndexWarningBlock(failures) {
|
|
13913
|
+
if (failures.length === 0) return "";
|
|
13914
|
+
const lines = failures.map((f) => {
|
|
13915
|
+
const reason = f.message ?? f.code ?? "indexing failed";
|
|
13916
|
+
return ` \u2022 ${f.typeName}/${f.externalId} (${f.surface}): ${reason}
|
|
13917
|
+
`;
|
|
13918
|
+
});
|
|
13919
|
+
return ` \u26A0 ${failures.length} seed(s) stored but not fully searchable:
|
|
13920
|
+
` + lines.join("") + ` They're stored and retrievable by id, but won't appear in search until the issue above is resolved.
|
|
13921
|
+
`;
|
|
13922
|
+
}
|
|
13831
13923
|
function reconcileTally(items, noun) {
|
|
13832
13924
|
if (items.length === 0) return null;
|
|
13833
13925
|
const created = items.filter((i) => i.action === "created").length;
|
|
@@ -14084,7 +14176,7 @@ ${renderPlan(blueprint, planSteps)}
|
|
|
14084
14176
|
noSeed,
|
|
14085
14177
|
declinedInteractively: seedDeclinedInteractively,
|
|
14086
14178
|
seededCount: result.seededCount
|
|
14087
|
-
})
|
|
14179
|
+
}) + seedIndexWarningBlock(result.seedIndexFailures)
|
|
14088
14180
|
);
|
|
14089
14181
|
const entry = buildVectrosServerEntry({ apiKey: result.rawKey, apiBaseUrl: baseUrl });
|
|
14090
14182
|
const isCode = args.client === "code";
|
|
@@ -15365,6 +15457,25 @@ function canonicalDim(key) {
|
|
|
15365
15457
|
if (key === "userId" || key === "partnerUserId") return "user";
|
|
15366
15458
|
return key;
|
|
15367
15459
|
}
|
|
15460
|
+
var FORBIDDEN_SCOPE_NAMESPACES = /* @__PURE__ */ new Set([
|
|
15461
|
+
"user",
|
|
15462
|
+
"record",
|
|
15463
|
+
"document",
|
|
15464
|
+
"entity",
|
|
15465
|
+
"self",
|
|
15466
|
+
"tenant",
|
|
15467
|
+
"context",
|
|
15468
|
+
"scope",
|
|
15469
|
+
"versions",
|
|
15470
|
+
"lookup"
|
|
15471
|
+
]);
|
|
15472
|
+
var SCOPE_NAMESPACE_RE = /^[a-z][a-z0-9_-]{1,31}$/;
|
|
15473
|
+
function isRecognizedOwnershipKey(key) {
|
|
15474
|
+
if (key === "userId" || key === "partnerUserId") return true;
|
|
15475
|
+
if (!key.startsWith("scope:")) return false;
|
|
15476
|
+
const ns = key.slice("scope:".length);
|
|
15477
|
+
return !FORBIDDEN_SCOPE_NAMESPACES.has(ns) && SCOPE_NAMESPACE_RE.test(ns);
|
|
15478
|
+
}
|
|
15368
15479
|
var SELF_TOKEN_RE2 = /^\$\{\{\s*self\.[a-zA-Z.]+\s*\}\}$/;
|
|
15369
15480
|
function normalizeClauses(raw) {
|
|
15370
15481
|
const out = [];
|
|
@@ -15374,15 +15485,18 @@ function normalizeClauses(raw) {
|
|
|
15374
15485
|
const actions = obj.allowed_actions ?? obj.allowedActions ?? [];
|
|
15375
15486
|
const ds = obj.data_scope ?? obj.dataScope ?? {};
|
|
15376
15487
|
const dataScope = {};
|
|
15488
|
+
const unrecognizedDims = [];
|
|
15377
15489
|
for (const [k, v] of Object.entries(ds)) {
|
|
15490
|
+
const dim = canonicalDim(k);
|
|
15378
15491
|
const values = Array.isArray(v) ? v : [v];
|
|
15379
|
-
dataScope[
|
|
15492
|
+
dataScope[dim] = values.map((val) => {
|
|
15380
15493
|
if (val === null) return null;
|
|
15381
15494
|
const s = String(val);
|
|
15382
15495
|
return SELF_TOKEN_RE2.test(s) ? SELF : s;
|
|
15383
15496
|
});
|
|
15497
|
+
if (!isRecognizedOwnershipKey(k)) unrecognizedDims.push(k);
|
|
15384
15498
|
}
|
|
15385
|
-
out.push({ actions: Array.isArray(actions) ? actions.map(String) : [], dataScope });
|
|
15499
|
+
out.push({ actions: Array.isArray(actions) ? actions.map(String) : [], dataScope, unrecognizedDims });
|
|
15386
15500
|
}
|
|
15387
15501
|
return out;
|
|
15388
15502
|
}
|
|
@@ -15393,6 +15507,7 @@ function buildArchetypes(clauses) {
|
|
|
15393
15507
|
];
|
|
15394
15508
|
const scopeDims = /* @__PURE__ */ new Map();
|
|
15395
15509
|
for (const c of clauses) {
|
|
15510
|
+
if (c.unrecognizedDims.length > 0) continue;
|
|
15396
15511
|
for (const [dim, values] of Object.entries(c.dataScope)) {
|
|
15397
15512
|
if (dim === "user") continue;
|
|
15398
15513
|
const set = scopeDims.get(dim) ?? /* @__PURE__ */ new Set();
|
|
@@ -15416,6 +15531,7 @@ function buildArchetypes(clauses) {
|
|
|
15416
15531
|
return rows;
|
|
15417
15532
|
}
|
|
15418
15533
|
function clauseMatches(clause, arch) {
|
|
15534
|
+
if (clause.unrecognizedDims.length > 0) return false;
|
|
15419
15535
|
for (const [dim, allowed] of Object.entries(clause.dataScope)) {
|
|
15420
15536
|
const recordValue = arch.owners[dim];
|
|
15421
15537
|
const ok = allowed.some((a) => {
|
|
@@ -15481,7 +15597,14 @@ async function runAccessExplain(opts, deps = {}) {
|
|
|
15481
15597
|
context: opts.context,
|
|
15482
15598
|
via,
|
|
15483
15599
|
identityOverrides: profile.identityOverrides,
|
|
15484
|
-
clauses: clauses.map((c, i) => ({
|
|
15600
|
+
clauses: clauses.map((c, i) => ({
|
|
15601
|
+
n: i + 1,
|
|
15602
|
+
actions: c.actions,
|
|
15603
|
+
dataScope: renderDataScope(c.dataScope),
|
|
15604
|
+
// Present only on a dead clause — an unrecognized dim the platform
|
|
15605
|
+
// denies (a retired key or a bad scope:<ns>); the matrix omits it.
|
|
15606
|
+
...c.unrecognizedDims.length > 0 ? { grantsNothing: true, unrecognizedDims: c.unrecognizedDims } : {}
|
|
15607
|
+
})),
|
|
15485
15608
|
matrix: rows,
|
|
15486
15609
|
note: "Ownership dimensions only: per-type action qualifiers narrow further, and search/RAG visibility is bounded per row by the same clause's typed read grants. Client-side preview; the platform decides at request time."
|
|
15487
15610
|
})}
|
|
@@ -15500,6 +15623,12 @@ async function runAccessExplain(opts, deps = {}) {
|
|
|
15500
15623
|
clauses.forEach((c, i) => {
|
|
15501
15624
|
process.stdout.write(` ${i + 1}. [${c.actions.join(", ")}] where ${renderDataScope(c.dataScope)}
|
|
15502
15625
|
`);
|
|
15626
|
+
if (c.unrecognizedDims.length > 0) {
|
|
15627
|
+
process.stdout.write(
|
|
15628
|
+
` \u2716 grants nothing \u2014 unrecognized dimension${c.unrecognizedDims.length > 1 ? "s" : ""}: ${c.unrecognizedDims.join(", ")} (the platform denies a clause keyed on any dim that is not userId or a valid scope:<namespace>)
|
|
15629
|
+
`
|
|
15630
|
+
);
|
|
15631
|
+
}
|
|
15503
15632
|
});
|
|
15504
15633
|
process.stdout.write(
|
|
15505
15634
|
"\n" + formatTable(rows, [
|
|
@@ -18245,9 +18374,9 @@ function emitJoined(alias, context, principalId, role, keyId, reused) {
|
|
|
18245
18374
|
|
|
18246
18375
|
// src/build-info.ts
|
|
18247
18376
|
var BUILD_INFO = {
|
|
18248
|
-
cli: true ? "0.
|
|
18249
|
-
sdk: true ? "0.
|
|
18250
|
-
blueprints: true ? "0.
|
|
18377
|
+
cli: true ? "0.12.0" : "dev",
|
|
18378
|
+
sdk: true ? "0.37.0" : "dev",
|
|
18379
|
+
blueprints: true ? "0.9.0" : "dev"
|
|
18251
18380
|
};
|
|
18252
18381
|
function formatBuildInfo() {
|
|
18253
18382
|
return `vectros ${BUILD_INFO.cli} (sdk ${BUILD_INFO.sdk}, blueprints ${BUILD_INFO.blueprints})`;
|