commonswarm 0.1.51 → 0.1.52
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/cswarm.cjs +192 -123
- package/package.json +1 -1
package/cswarm.cjs
CHANGED
|
@@ -26624,6 +26624,138 @@ function parseAgentCredentialInput(value, source) {
|
|
|
26624
26624
|
|
|
26625
26625
|
// src/cloud/renewal.ts
|
|
26626
26626
|
var import_node_crypto9 = require("node:crypto");
|
|
26627
|
+
|
|
26628
|
+
// src/cloud/renewal-grants.ts
|
|
26629
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
26630
|
+
function nullableString(value, field) {
|
|
26631
|
+
if (value === null) return null;
|
|
26632
|
+
if (typeof value !== "string") {
|
|
26633
|
+
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
26634
|
+
}
|
|
26635
|
+
return value;
|
|
26636
|
+
}
|
|
26637
|
+
function nullableTimestamp(value, field) {
|
|
26638
|
+
const text = nullableString(value, field);
|
|
26639
|
+
if (text !== null && !Number.isFinite(Date.parse(text))) {
|
|
26640
|
+
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
26641
|
+
}
|
|
26642
|
+
return text;
|
|
26643
|
+
}
|
|
26644
|
+
function uuid2(value, field) {
|
|
26645
|
+
if (typeof value !== "string" || !UUID_RE5.test(value)) {
|
|
26646
|
+
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
26647
|
+
}
|
|
26648
|
+
return value.toLowerCase();
|
|
26649
|
+
}
|
|
26650
|
+
function nullableUuid(value, field) {
|
|
26651
|
+
return value === null ? null : uuid2(value, field);
|
|
26652
|
+
}
|
|
26653
|
+
function parseGrant(value) {
|
|
26654
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
26655
|
+
throw new Error("renewal grant read returned a malformed row");
|
|
26656
|
+
}
|
|
26657
|
+
const row = value;
|
|
26658
|
+
if (row.kind !== "timeboxed" && row.kind !== "standing") {
|
|
26659
|
+
throw new Error("renewal grant read returned malformed kind");
|
|
26660
|
+
}
|
|
26661
|
+
const horizon = nullableTimestamp(
|
|
26662
|
+
row.horizon_expires_at,
|
|
26663
|
+
"horizon_expires_at"
|
|
26664
|
+
);
|
|
26665
|
+
if (row.kind === "standing" && horizon !== null || row.kind === "timeboxed" && horizon === null) {
|
|
26666
|
+
throw new Error("renewal grant read returned an invalid kind/horizon pair");
|
|
26667
|
+
}
|
|
26668
|
+
return {
|
|
26669
|
+
renewal_grant_id: uuid2(row.renewal_grant_id, "renewal_grant_id"),
|
|
26670
|
+
principal_id: uuid2(row.principal_id, "principal_id"),
|
|
26671
|
+
kind: row.kind,
|
|
26672
|
+
horizon_expires_at: horizon,
|
|
26673
|
+
bound_device_id: nullableUuid(row.bound_device_id, "bound_device_id"),
|
|
26674
|
+
last_used_at: nullableTimestamp(row.last_used_at, "last_used_at"),
|
|
26675
|
+
last_used_device_id: nullableUuid(
|
|
26676
|
+
row.last_used_device_id,
|
|
26677
|
+
"last_used_device_id"
|
|
26678
|
+
),
|
|
26679
|
+
last_used_from: nullableString(row.last_used_from, "last_used_from"),
|
|
26680
|
+
new_host_at: nullableTimestamp(row.new_host_at, "new_host_at"),
|
|
26681
|
+
suspended_at: nullableTimestamp(row.suspended_at, "suspended_at"),
|
|
26682
|
+
revoked_at: nullableTimestamp(row.revoked_at, "revoked_at"),
|
|
26683
|
+
token_id: nullableUuid(row.token_id, "token_id"),
|
|
26684
|
+
issued_at: nullableTimestamp(row.issued_at, "issued_at"),
|
|
26685
|
+
token_expires_at: nullableTimestamp(
|
|
26686
|
+
row.token_expires_at,
|
|
26687
|
+
"token_expires_at"
|
|
26688
|
+
),
|
|
26689
|
+
token_revoked_at: nullableTimestamp(
|
|
26690
|
+
row.token_revoked_at,
|
|
26691
|
+
"token_revoked_at"
|
|
26692
|
+
)
|
|
26693
|
+
};
|
|
26694
|
+
}
|
|
26695
|
+
async function readRenewalGrants(target2, credential, workspaceId2, fetcher = fetch) {
|
|
26696
|
+
const response = await fetcher(readEndpoint(target2), {
|
|
26697
|
+
method: "POST",
|
|
26698
|
+
headers: {
|
|
26699
|
+
authorization: `Bearer ${credential}`,
|
|
26700
|
+
apikey: target2.anonKey,
|
|
26701
|
+
"content-type": "application/json"
|
|
26702
|
+
},
|
|
26703
|
+
body: JSON.stringify({
|
|
26704
|
+
resource: "renewal_grants",
|
|
26705
|
+
workspace_id: workspaceId2
|
|
26706
|
+
}),
|
|
26707
|
+
signal: AbortSignal.timeout(15e3)
|
|
26708
|
+
});
|
|
26709
|
+
if (!response.ok) {
|
|
26710
|
+
throw new Error(`renewal grant read failed (HTTP ${response.status})`);
|
|
26711
|
+
}
|
|
26712
|
+
const body = await response.json().catch(() => null);
|
|
26713
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
26714
|
+
throw new Error("renewal grant read returned malformed JSON");
|
|
26715
|
+
}
|
|
26716
|
+
const grants = body.grants;
|
|
26717
|
+
if (!Array.isArray(grants)) {
|
|
26718
|
+
throw new Error("renewal grant read returned no grants array");
|
|
26719
|
+
}
|
|
26720
|
+
return grants.map(parseGrant);
|
|
26721
|
+
}
|
|
26722
|
+
var STANDING_IDLE_PAUSE_DAYS = 14;
|
|
26723
|
+
var STANDING_RESUME_ACTORS = [
|
|
26724
|
+
"a workspace owner",
|
|
26725
|
+
"an admin",
|
|
26726
|
+
"the member who added the agent"
|
|
26727
|
+
];
|
|
26728
|
+
function orList(items) {
|
|
26729
|
+
if (items.length === 0) return "";
|
|
26730
|
+
if (items.length === 1) return items[0];
|
|
26731
|
+
return `${items.slice(0, -1).join(", ")}, or ${items[items.length - 1]}`;
|
|
26732
|
+
}
|
|
26733
|
+
var STANDING_RESUME_ACTORS_SENTENCE = orList(STANDING_RESUME_ACTORS);
|
|
26734
|
+
var STANDING_GRANT_RULES = [
|
|
26735
|
+
"Access does not expire.",
|
|
26736
|
+
`${STANDING_IDLE_PAUSE_DAYS} days with no use pauses it; ${STANDING_RESUME_ACTORS_SENTENCE} can resume it.`,
|
|
26737
|
+
"Revoking it is the only permanent stop."
|
|
26738
|
+
];
|
|
26739
|
+
function standingPausedRenewalMessage(idle) {
|
|
26740
|
+
const cause = idle ? `This standing grant went ${STANDING_IDLE_PAUSE_DAYS} days with no use, so CommonSwarm paused it and refused renewal.` : "This renewal grant is paused, so CommonSwarm refused renewal.";
|
|
26741
|
+
return `${cause} It is not revoked and this agent is not gone. Next step: ${STANDING_RESUME_ACTORS_SENTENCE} runs cswarm grant resume, then this agent continues.`;
|
|
26742
|
+
}
|
|
26743
|
+
function describeRenewalGrant(grant) {
|
|
26744
|
+
const lines = grant.kind === "standing" ? [`Grant: standing \u2014 ${STANDING_GRANT_RULES.join(" ")}`] : [`Grant: timeboxed \u2014 renewal horizon ${grant.horizon_expires_at}.`];
|
|
26745
|
+
if (grant.suspended_at !== null) {
|
|
26746
|
+
lines.push(
|
|
26747
|
+
`PAUSED since ${grant.suspended_at} after ${STANDING_IDLE_PAUSE_DAYS} days with no use. This is not revoked and the agent is not gone. Next step: ${orList(STANDING_RESUME_ACTORS)} runs cswarm grant resume --renewal-grant-id ${grant.renewal_grant_id}`
|
|
26748
|
+
);
|
|
26749
|
+
}
|
|
26750
|
+
if (grant.revoked_at !== null) {
|
|
26751
|
+
lines.push(
|
|
26752
|
+
`REVOKED since ${grant.revoked_at}. This is permanent and cannot be resumed. Next step: mint a new grant if this agent should continue.`
|
|
26753
|
+
);
|
|
26754
|
+
}
|
|
26755
|
+
return lines;
|
|
26756
|
+
}
|
|
26757
|
+
|
|
26758
|
+
// src/cloud/renewal.ts
|
|
26627
26759
|
var AGENT_TOKEN_DEFAULT_TTL_MS2 = 60 * 60 * 1e3;
|
|
26628
26760
|
var AGENT_TOKEN_MAX_TTL_MS2 = 8 * 60 * 60 * 1e3;
|
|
26629
26761
|
var RENEWAL_HORIZON_DEFAULT_MS2 = 30 * 24 * 60 * 60 * 1e3;
|
|
@@ -26633,7 +26765,8 @@ function describeMintRenewal(hasExpiry, horizonDays, kind = "timeboxed") {
|
|
|
26633
26765
|
return "This credential does not renew itself; re-issue one by hand when it expires.\n";
|
|
26634
26766
|
}
|
|
26635
26767
|
if (kind === "standing") {
|
|
26636
|
-
return
|
|
26768
|
+
return `Standing grant created. ${STANDING_GRANT_RULES.join(" ")} The bearer credential still rotates before expiry while a cswarm process remains running and secure local state is available.
|
|
26769
|
+
`;
|
|
26637
26770
|
}
|
|
26638
26771
|
const days = Number.isFinite(horizonDays) && horizonDays > 0 ? Math.round(horizonDays) : Math.round(RENEWAL_HORIZON_DEFAULT_MS2 / 864e5);
|
|
26639
26772
|
return `While a cswarm process remains running and secure local state is available, this credential rotates before expiry. A person is asked to authorise it again in ${days} days. A stopped or idle CLI cannot renew it.
|
|
@@ -26644,7 +26777,7 @@ var RENEWAL_LEAD_FLOOR_MS = 5 * 6e4;
|
|
|
26644
26777
|
var RENEWAL_LEAD_CEILING_MS = 15 * 6e4;
|
|
26645
26778
|
var RENEWAL_PENDING_RECOVERY_MS = 60 * 6e4;
|
|
26646
26779
|
var RENEW_TIMEOUT_MS = 3e4;
|
|
26647
|
-
var
|
|
26780
|
+
var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
26648
26781
|
var AGENT_TOKEN_RE4 = /^swm_agt_[A-Za-z0-9_-]{43}$/;
|
|
26649
26782
|
function renewalDueAt(issuedAt, expiresAt) {
|
|
26650
26783
|
const lifetime = Math.max(0, expiresAt - issuedAt);
|
|
@@ -26803,7 +26936,7 @@ async function requestSuccessor(options) {
|
|
|
26803
26936
|
} catch {
|
|
26804
26937
|
body = {};
|
|
26805
26938
|
}
|
|
26806
|
-
const principalId = typeof body.principal_id === "string" &&
|
|
26939
|
+
const principalId = typeof body.principal_id === "string" && UUID_RE6.test(body.principal_id) ? body.principal_id.toLowerCase() : null;
|
|
26807
26940
|
if (response.status === 400 || response.status === 404) {
|
|
26808
26941
|
throw new RenewalUnsupported(
|
|
26809
26942
|
"this deployment does not offer credential renewal yet, so a credential here still has to be re-issued by hand when it expires"
|
|
@@ -26838,7 +26971,7 @@ async function requestSuccessor(options) {
|
|
|
26838
26971
|
if (reason === "renewal_idle_suspended" || reason === "renewal_grant_suspended") {
|
|
26839
26972
|
throw new RenewalSuspended(
|
|
26840
26973
|
reason,
|
|
26841
|
-
reason === "renewal_idle_suspended"
|
|
26974
|
+
standingPausedRenewalMessage(reason === "renewal_idle_suspended")
|
|
26842
26975
|
);
|
|
26843
26976
|
}
|
|
26844
26977
|
if (reason === "renewal_horizon_reached") {
|
|
@@ -26900,7 +27033,7 @@ async function requestSuccessor(options) {
|
|
|
26900
27033
|
}
|
|
26901
27034
|
const tokenId = typeof body.token_id === "string" ? body.token_id : "";
|
|
26902
27035
|
const runId = typeof body.run_id === "string" ? body.run_id : "";
|
|
26903
|
-
if (!
|
|
27036
|
+
if (!UUID_RE6.test(tokenId) || !UUID_RE6.test(runId) || principalId === null) {
|
|
26904
27037
|
throw new RenewalRefused(
|
|
26905
27038
|
response.status,
|
|
26906
27039
|
"incomplete_successor",
|
|
@@ -27409,7 +27542,7 @@ var MAX_LINK_PAYLOAD_BYTES = 8 * 1024;
|
|
|
27409
27542
|
var MAX_LABEL_INPUT_LENGTH = 1024;
|
|
27410
27543
|
var CONTROL_GLOBAL_RE = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g;
|
|
27411
27544
|
var ANSI_ESCAPE_GLOBAL_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
27412
|
-
var
|
|
27545
|
+
var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
27413
27546
|
var STRICT_BASE64URL_RE = /^[A-Za-z0-9_-]+$/;
|
|
27414
27547
|
var RAW_BASE64_PAYLOAD_CANDIDATE_RE = /^[A-Za-z0-9+/_=-]+$/;
|
|
27415
27548
|
var CURRENT_INVITE_SCHEME = "cswarm://accept/";
|
|
@@ -27460,7 +27593,7 @@ function validatedPayload(value) {
|
|
|
27460
27593
|
throw new Error("invite link target is malformed");
|
|
27461
27594
|
}
|
|
27462
27595
|
cloudTarget(value.url, value.anon_key);
|
|
27463
|
-
if (typeof value.workspace_id !== "string" || !
|
|
27596
|
+
if (typeof value.workspace_id !== "string" || !UUID_RE7.test(value.workspace_id)) {
|
|
27464
27597
|
throw new Error("invite link workspace_id must be a UUID");
|
|
27465
27598
|
}
|
|
27466
27599
|
if (typeof value.invitation_token !== "string") {
|
|
@@ -27470,7 +27603,7 @@ function validatedPayload(value) {
|
|
|
27470
27603
|
if (typeof value.workspace_name !== "string" || typeof value.inviter_display_name !== "string" || value.workspace_name.length > MAX_LABEL_INPUT_LENGTH || value.inviter_display_name.length > MAX_LABEL_INPUT_LENGTH) {
|
|
27471
27604
|
throw new Error("invite link display labels are malformed");
|
|
27472
27605
|
}
|
|
27473
|
-
if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !
|
|
27606
|
+
if (value.inviter_user_id !== void 0 && (typeof value.inviter_user_id !== "string" || !UUID_RE7.test(value.inviter_user_id))) {
|
|
27474
27607
|
throw new Error("invite link inviter_user_id must be a UUID");
|
|
27475
27608
|
}
|
|
27476
27609
|
return value;
|
|
@@ -27670,7 +27803,7 @@ function acceptedResponse(result) {
|
|
|
27670
27803
|
}
|
|
27671
27804
|
return result.response;
|
|
27672
27805
|
}
|
|
27673
|
-
function
|
|
27806
|
+
function uuid3(value, field) {
|
|
27674
27807
|
if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
|
|
27675
27808
|
throw new Error(`server returned a malformed ${field}`);
|
|
27676
27809
|
}
|
|
@@ -28014,7 +28147,7 @@ function cloudAcceptOperations(target2, store2, fetcher = fetch) {
|
|
|
28014
28147
|
);
|
|
28015
28148
|
return {
|
|
28016
28149
|
status: "accepted",
|
|
28017
|
-
workspaceId:
|
|
28150
|
+
workspaceId: uuid3(response.workspace_id, "workspace_id")
|
|
28018
28151
|
};
|
|
28019
28152
|
} catch (error) {
|
|
28020
28153
|
if (error instanceof CommandHttpError && error.status === 403) {
|
|
@@ -28033,7 +28166,7 @@ function cloudAcceptOperations(target2, store2, fetcher = fetch) {
|
|
|
28033
28166
|
if (result.response.status === "accepted") {
|
|
28034
28167
|
return {
|
|
28035
28168
|
status: "accepted",
|
|
28036
|
-
principalId:
|
|
28169
|
+
principalId: uuid3(result.response.principal_id, "principal_id")
|
|
28037
28170
|
};
|
|
28038
28171
|
}
|
|
28039
28172
|
if (String(result.response.reason) === "principal_name_taken") {
|
|
@@ -28127,113 +28260,6 @@ function renderCapabilityRevoke(capabilityId, revokedAt) {
|
|
|
28127
28260
|
return `Capability link ${capabilityId} was revoked at ${revokedAt}. Anyone who still holds it now gets the same answer as someone holding a link that never existed. Links you have not revoked are unaffected.`;
|
|
28128
28261
|
}
|
|
28129
28262
|
|
|
28130
|
-
// src/cloud/renewal-grants.ts
|
|
28131
|
-
var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28132
|
-
function nullableString(value, field) {
|
|
28133
|
-
if (value === null) return null;
|
|
28134
|
-
if (typeof value !== "string") {
|
|
28135
|
-
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
28136
|
-
}
|
|
28137
|
-
return value;
|
|
28138
|
-
}
|
|
28139
|
-
function nullableTimestamp(value, field) {
|
|
28140
|
-
const text = nullableString(value, field);
|
|
28141
|
-
if (text !== null && !Number.isFinite(Date.parse(text))) {
|
|
28142
|
-
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
28143
|
-
}
|
|
28144
|
-
return text;
|
|
28145
|
-
}
|
|
28146
|
-
function uuid3(value, field) {
|
|
28147
|
-
if (typeof value !== "string" || !UUID_RE7.test(value)) {
|
|
28148
|
-
throw new Error(`renewal grant read returned malformed ${field}`);
|
|
28149
|
-
}
|
|
28150
|
-
return value.toLowerCase();
|
|
28151
|
-
}
|
|
28152
|
-
function nullableUuid(value, field) {
|
|
28153
|
-
return value === null ? null : uuid3(value, field);
|
|
28154
|
-
}
|
|
28155
|
-
function parseGrant(value) {
|
|
28156
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
28157
|
-
throw new Error("renewal grant read returned a malformed row");
|
|
28158
|
-
}
|
|
28159
|
-
const row = value;
|
|
28160
|
-
if (row.kind !== "timeboxed" && row.kind !== "standing") {
|
|
28161
|
-
throw new Error("renewal grant read returned malformed kind");
|
|
28162
|
-
}
|
|
28163
|
-
const horizon = nullableTimestamp(
|
|
28164
|
-
row.horizon_expires_at,
|
|
28165
|
-
"horizon_expires_at"
|
|
28166
|
-
);
|
|
28167
|
-
if (row.kind === "standing" && horizon !== null || row.kind === "timeboxed" && horizon === null) {
|
|
28168
|
-
throw new Error("renewal grant read returned an invalid kind/horizon pair");
|
|
28169
|
-
}
|
|
28170
|
-
return {
|
|
28171
|
-
renewal_grant_id: uuid3(row.renewal_grant_id, "renewal_grant_id"),
|
|
28172
|
-
principal_id: uuid3(row.principal_id, "principal_id"),
|
|
28173
|
-
kind: row.kind,
|
|
28174
|
-
horizon_expires_at: horizon,
|
|
28175
|
-
bound_device_id: nullableUuid(row.bound_device_id, "bound_device_id"),
|
|
28176
|
-
last_used_at: nullableTimestamp(row.last_used_at, "last_used_at"),
|
|
28177
|
-
last_used_device_id: nullableUuid(
|
|
28178
|
-
row.last_used_device_id,
|
|
28179
|
-
"last_used_device_id"
|
|
28180
|
-
),
|
|
28181
|
-
last_used_from: nullableString(row.last_used_from, "last_used_from"),
|
|
28182
|
-
new_host_at: nullableTimestamp(row.new_host_at, "new_host_at"),
|
|
28183
|
-
suspended_at: nullableTimestamp(row.suspended_at, "suspended_at"),
|
|
28184
|
-
revoked_at: nullableTimestamp(row.revoked_at, "revoked_at"),
|
|
28185
|
-
token_id: nullableUuid(row.token_id, "token_id"),
|
|
28186
|
-
issued_at: nullableTimestamp(row.issued_at, "issued_at"),
|
|
28187
|
-
token_expires_at: nullableTimestamp(
|
|
28188
|
-
row.token_expires_at,
|
|
28189
|
-
"token_expires_at"
|
|
28190
|
-
),
|
|
28191
|
-
token_revoked_at: nullableTimestamp(
|
|
28192
|
-
row.token_revoked_at,
|
|
28193
|
-
"token_revoked_at"
|
|
28194
|
-
)
|
|
28195
|
-
};
|
|
28196
|
-
}
|
|
28197
|
-
async function readRenewalGrants(target2, credential, workspaceId2, fetcher = fetch) {
|
|
28198
|
-
const response = await fetcher(readEndpoint(target2), {
|
|
28199
|
-
method: "POST",
|
|
28200
|
-
headers: {
|
|
28201
|
-
authorization: `Bearer ${credential}`,
|
|
28202
|
-
apikey: target2.anonKey,
|
|
28203
|
-
"content-type": "application/json"
|
|
28204
|
-
},
|
|
28205
|
-
body: JSON.stringify({
|
|
28206
|
-
resource: "renewal_grants",
|
|
28207
|
-
workspace_id: workspaceId2
|
|
28208
|
-
}),
|
|
28209
|
-
signal: AbortSignal.timeout(15e3)
|
|
28210
|
-
});
|
|
28211
|
-
if (!response.ok) {
|
|
28212
|
-
throw new Error(`renewal grant read failed (HTTP ${response.status})`);
|
|
28213
|
-
}
|
|
28214
|
-
const body = await response.json().catch(() => null);
|
|
28215
|
-
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
28216
|
-
throw new Error("renewal grant read returned malformed JSON");
|
|
28217
|
-
}
|
|
28218
|
-
const grants = body.grants;
|
|
28219
|
-
if (!Array.isArray(grants)) {
|
|
28220
|
-
throw new Error("renewal grant read returned no grants array");
|
|
28221
|
-
}
|
|
28222
|
-
return grants.map(parseGrant);
|
|
28223
|
-
}
|
|
28224
|
-
function describeRenewalGrant(grant) {
|
|
28225
|
-
const lines = grant.kind === "standing" ? ["Grant: standing \u2014 does not expire; revoke is the only kill switch."] : [`Grant: timeboxed \u2014 renewal horizon ${grant.horizon_expires_at}.`];
|
|
28226
|
-
if (grant.suspended_at !== null) {
|
|
28227
|
-
lines.push(
|
|
28228
|
-
`SUSPENDED since ${grant.suspended_at}. Next step: ask a workspace owner to revoke this grant and mint a new credential.`
|
|
28229
|
-
);
|
|
28230
|
-
}
|
|
28231
|
-
if (grant.revoked_at !== null) {
|
|
28232
|
-
lines.push(`REVOKED since ${grant.revoked_at}. Next step: mint a new grant if this agent should continue.`);
|
|
28233
|
-
}
|
|
28234
|
-
return lines;
|
|
28235
|
-
}
|
|
28236
|
-
|
|
28237
28263
|
// src/cloud/workspaces.ts
|
|
28238
28264
|
var UUID_RE8 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28239
28265
|
var ROLES = /* @__PURE__ */ new Set(["owner", "admin", "member"]);
|
|
@@ -31102,7 +31128,7 @@ var DELIVERY_HANDLED_OUTCOMES = new Set(
|
|
|
31102
31128
|
var DELIVERY_PROVIDER_PROVEN_OUTCOMES = new Set(
|
|
31103
31129
|
[...DELIVERY_ACK_OUTCOMES].filter((outcome) => outcome === "replied")
|
|
31104
31130
|
);
|
|
31105
|
-
function
|
|
31131
|
+
function orList2(values2) {
|
|
31106
31132
|
return values2.length <= 1 ? values2.join("") : `${values2.slice(0, -1).join(", ")}, or ${values2[values2.length - 1]}`;
|
|
31107
31133
|
}
|
|
31108
31134
|
var DELIVERY_REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -31448,13 +31474,13 @@ function assertAckRequest(request) {
|
|
|
31448
31474
|
checkedUuidRequest(request.listenerInstanceId, "listenerInstanceId");
|
|
31449
31475
|
if (!DELIVERY_ACK_OUTCOMES.has(request.outcome)) {
|
|
31450
31476
|
throw new Error(
|
|
31451
|
-
`a delivery outcome must be ${
|
|
31477
|
+
`a delivery outcome must be ${orList2([...DELIVERY_ACK_OUTCOMES])}`
|
|
31452
31478
|
);
|
|
31453
31479
|
}
|
|
31454
31480
|
if (request.outcome === "failed_terminal") {
|
|
31455
31481
|
if (typeof request.lastErrorCode !== "string" || !FAILED_TERMINAL_CODES_SET.has(request.lastErrorCode)) {
|
|
31456
31482
|
throw new Error(
|
|
31457
|
-
`a failed_terminal acknowledgement requires one of ${
|
|
31483
|
+
`a failed_terminal acknowledgement requires one of ${orList2([...FAILED_TERMINAL_CODES_SET])}`
|
|
31458
31484
|
);
|
|
31459
31485
|
}
|
|
31460
31486
|
} else if (request.lastErrorCode !== null) {
|
|
@@ -41978,6 +42004,7 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
41978
42004
|
"permissions",
|
|
41979
42005
|
"principal-id",
|
|
41980
42006
|
"provider",
|
|
42007
|
+
"renewal-grant-id",
|
|
41981
42008
|
"repo",
|
|
41982
42009
|
"reveal-anon-key",
|
|
41983
42010
|
"route",
|
|
@@ -42029,8 +42056,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
42029
42056
|
]);
|
|
42030
42057
|
var UUID_RE23 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
42031
42058
|
function packageVersion() {
|
|
42032
|
-
if ("0.1.
|
|
42033
|
-
return "0.1.
|
|
42059
|
+
if ("0.1.52".length > 0) {
|
|
42060
|
+
return "0.1.52";
|
|
42034
42061
|
}
|
|
42035
42062
|
try {
|
|
42036
42063
|
const value = JSON.parse(
|
|
@@ -42191,6 +42218,7 @@ Usage:
|
|
|
42191
42218
|
cswarm token mint [--url <url> --anon-key <key>] [--workspace-id <uuid>] --principal-id <uuid> --run-id <uuid> --task-id <uuid> --epoch <n> [--ttl-ms <ms>] [--renewal-horizon-days <1..90> | --standing --confirm-standing]
|
|
42192
42219
|
cswarm token revoke [--url <url> --anon-key <key>] [--workspace-id <uuid>] --token-id <uuid>
|
|
42193
42220
|
cswarm token revoke ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> [--token-id <uuid>]
|
|
42221
|
+
cswarm grant resume [--url <url> --anon-key <key>] [--workspace-id <uuid>] --renewal-grant-id <uuid> [--json] # lifts an idle pause; a REVOKED grant is refused
|
|
42194
42222
|
cswarm link new [--url <url> --anon-key <key>] [--workspace-id <uuid>] --task-id <uuid> [--ttl-ms <ms>] [--site <origin>] [--json]
|
|
42195
42223
|
cswarm link revoke [--url <url> --anon-key <key>] [--workspace-id <uuid>] --capability-id <uuid> [--json]
|
|
42196
42224
|
cswarm command <kind> [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [command fields]
|
|
@@ -43333,6 +43361,43 @@ async function runToken(args) {
|
|
|
43333
43361
|
expiresAt
|
|
43334
43362
|
}));
|
|
43335
43363
|
}
|
|
43364
|
+
async function runGrant(args) {
|
|
43365
|
+
const action = args.positionals[1];
|
|
43366
|
+
args.assertShape(
|
|
43367
|
+
[
|
|
43368
|
+
...TARGET_FLAGS,
|
|
43369
|
+
"workspace-id",
|
|
43370
|
+
"renewal-grant-id",
|
|
43371
|
+
/* `--json` accepted, no effect — see the note on `runInvite`. D-064. */
|
|
43372
|
+
"json"
|
|
43373
|
+
],
|
|
43374
|
+
2
|
|
43375
|
+
);
|
|
43376
|
+
if (action !== "resume") {
|
|
43377
|
+
throw new UsageError(`unknown grant command: ${action ?? "(missing)"}`);
|
|
43378
|
+
}
|
|
43379
|
+
const renewalGrantId = args.required("renewal-grant-id");
|
|
43380
|
+
const cloud = await target(args);
|
|
43381
|
+
const human = await humanCredential(args, cloud);
|
|
43382
|
+
const workspace = await workspaceId(args, cloud, human);
|
|
43383
|
+
const response = acceptedConnect(
|
|
43384
|
+
"grant resume",
|
|
43385
|
+
await sendConnectWithPending(
|
|
43386
|
+
new ThinCommandClient(cloud),
|
|
43387
|
+
human,
|
|
43388
|
+
workspace,
|
|
43389
|
+
{ kind: "resume_renewal_grant", renewal_grant_id: renewalGrantId }
|
|
43390
|
+
)
|
|
43391
|
+
);
|
|
43392
|
+
const resumedAt = response.resumed_at ?? null;
|
|
43393
|
+
process.stdout.write(
|
|
43394
|
+
`Grant resumed${resumedAt === null ? "" : ` at ${resumedAt}`}.
|
|
43395
|
+
Renewal is allowed again. Nothing has reached the agent yet: it starts renewing when its own cswarm process next tries, so start that process if it is not running.
|
|
43396
|
+
The idle clock restarts now \u2014 another ${STANDING_IDLE_PAUSE_DAYS} days with no use pauses it again.
|
|
43397
|
+
Confirm with: cswarm whoami --agent-token-file <path>
|
|
43398
|
+
`
|
|
43399
|
+
);
|
|
43400
|
+
}
|
|
43336
43401
|
async function runTokenRevoke(args) {
|
|
43337
43402
|
if (hasAgentCredential(args)) {
|
|
43338
43403
|
args.assertShape(
|
|
@@ -47463,6 +47528,10 @@ async function main() {
|
|
|
47463
47528
|
await runToken(args);
|
|
47464
47529
|
return;
|
|
47465
47530
|
}
|
|
47531
|
+
if (verb === "grant") {
|
|
47532
|
+
await runGrant(args);
|
|
47533
|
+
return;
|
|
47534
|
+
}
|
|
47466
47535
|
if (verb === "link") {
|
|
47467
47536
|
await runLink(args);
|
|
47468
47537
|
return;
|