artifactpass 0.1.0-rc.2 → 0.1.0-rc.4
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/cli.mjs +534 -97
- package/dist/deployment/index.js +625 -50
- package/dist/deployment/migrations/0007-public-auth.sql +26 -0
- package/dist/deployment/wrangler-template.json +15 -4
- package/dist/marketplace/plugins/artifactpass/.claude-plugin/plugin.json +1 -1
- package/dist/marketplace/plugins/artifactpass/.codex-plugin/plugin.json +1 -1
- package/dist/marketplace/plugins/artifactpass/dist/cli.mjs +55 -12
- package/dist/marketplace/plugins/artifactpass/plugin-metadata.json +1 -1
- package/dist/marketplace/plugins/artifactpass/skills/share-artifact/SKILL.md +1 -1
- package/package.json +5 -1
package/dist/cli.mjs
CHANGED
|
@@ -14821,6 +14821,33 @@ import { spawn } from "node:child_process";
|
|
|
14821
14821
|
var ARTIFACTPASS_CREDENTIAL_SERVICE = "artifactpass";
|
|
14822
14822
|
var LEGACY_ARTIFACT_SHARE_CREDENTIAL_SERVICE = "lordebuilds.artifacts.share";
|
|
14823
14823
|
var agentCredentialAccountForProfile = (profileName) => profileName === "production" ? "agent-token" : `agent-token:${profileName}`;
|
|
14824
|
+
var agentTokenPattern = /^as_[A-Za-z0-9_-]{43}$/u;
|
|
14825
|
+
var bindAgentCredential = (originValue, token) => {
|
|
14826
|
+
if (!agentTokenPattern.test(token)) throw new Error("ArtifactPass agent credential is malformed");
|
|
14827
|
+
return JSON.stringify({ version: 1, origin: new URL(originValue).origin, token });
|
|
14828
|
+
};
|
|
14829
|
+
var resolveAgentCredential = (storedValue, expectedOriginValue, requireOriginBinding = false) => {
|
|
14830
|
+
if (agentTokenPattern.test(storedValue)) {
|
|
14831
|
+
if (requireOriginBinding) {
|
|
14832
|
+
throw new Error("ArtifactPass credential predates origin binding; reconnect this profile before publishing");
|
|
14833
|
+
}
|
|
14834
|
+
return storedValue;
|
|
14835
|
+
}
|
|
14836
|
+
let parsed;
|
|
14837
|
+
try {
|
|
14838
|
+
parsed = JSON.parse(storedValue);
|
|
14839
|
+
} catch {
|
|
14840
|
+
throw new Error("ArtifactPass agent credential is malformed");
|
|
14841
|
+
}
|
|
14842
|
+
if (parsed === null || typeof parsed !== "object" || parsed.version !== 1 || typeof parsed.origin !== "string" || typeof parsed.token !== "string" || !agentTokenPattern.test(parsed.token)) {
|
|
14843
|
+
throw new Error("ArtifactPass agent credential is malformed");
|
|
14844
|
+
}
|
|
14845
|
+
const expectedOrigin = new URL(expectedOriginValue).origin;
|
|
14846
|
+
if (new URL(parsed.origin).origin !== expectedOrigin) {
|
|
14847
|
+
throw new Error("ArtifactPass credential belongs to a different deployment; reconnect this profile");
|
|
14848
|
+
}
|
|
14849
|
+
return parsed.token;
|
|
14850
|
+
};
|
|
14824
14851
|
var CredentialStoreCommandError = class extends Error {
|
|
14825
14852
|
constructor(status) {
|
|
14826
14853
|
super(`Credential store command failed with status ${status ?? "unknown"}`);
|
|
@@ -14987,6 +15014,9 @@ var validateProfile = (value2) => {
|
|
|
14987
15014
|
if (candidate.credential_namespace !== void 0 && candidate.credential_namespace !== "artifactpass") {
|
|
14988
15015
|
throw new Error("ArtifactPass config contains an invalid credential namespace");
|
|
14989
15016
|
}
|
|
15017
|
+
if (candidate.credential_binding !== void 0 && candidate.credential_binding !== "origin") {
|
|
15018
|
+
throw new Error("ArtifactPass config contains an invalid credential binding");
|
|
15019
|
+
}
|
|
14990
15020
|
if (candidate.open_development !== void 0 && candidate.open_development !== true) {
|
|
14991
15021
|
throw new Error("ArtifactPass config open_development must be true when enabled");
|
|
14992
15022
|
}
|
|
@@ -15006,7 +15036,8 @@ var validateProfile = (value2) => {
|
|
|
15006
15036
|
...typeof candidate.pdf_key_id === "string" ? { pdf_key_id: candidate.pdf_key_id } : {},
|
|
15007
15037
|
...candidate.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
15008
15038
|
...typeof candidate.publication_state_path === "string" ? { publication_state_path: candidate.publication_state_path } : {},
|
|
15009
|
-
...candidate.credential_namespace === "artifactpass" ? { credential_namespace: "artifactpass" } : {}
|
|
15039
|
+
...candidate.credential_namespace === "artifactpass" ? { credential_namespace: "artifactpass" } : {},
|
|
15040
|
+
...candidate.credential_binding === "origin" ? { credential_binding: "origin" } : {}
|
|
15010
15041
|
};
|
|
15011
15042
|
};
|
|
15012
15043
|
var validateSettings = (value2) => {
|
|
@@ -15108,10 +15139,10 @@ import { DatabaseSync } from "node:sqlite";
|
|
|
15108
15139
|
|
|
15109
15140
|
// ../agent-bridge/src/logging/redacting-logger.ts
|
|
15110
15141
|
var bearerPattern = /\bBearer\s+[A-Za-z0-9._~-]+/giu;
|
|
15111
|
-
var
|
|
15142
|
+
var agentTokenPattern2 = /\bas_[A-Za-z0-9_-]{20,}\b/gu;
|
|
15112
15143
|
var cloudflareTokenPattern = /\bcfut_[A-Za-z0-9_-]{20,}\b/gu;
|
|
15113
15144
|
var shareUrlPattern = /https:\/\/[^\s/]+\/a\/[A-Za-z0-9_-]{32,256}(?:\/[^\s]*)?/gu;
|
|
15114
|
-
var redactSensitiveText = (value2) => value2.replace(bearerPattern, "Bearer [REDACTED]").replace(
|
|
15145
|
+
var redactSensitiveText = (value2) => value2.replace(bearerPattern, "Bearer [REDACTED]").replace(agentTokenPattern2, "[REDACTED]").replace(cloudflareTokenPattern, "[REDACTED]").replace(shareUrlPattern, "[REDACTED SHARE URL]");
|
|
15115
15146
|
|
|
15116
15147
|
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
|
|
15117
15148
|
var __create = Object.create;
|
|
@@ -28268,7 +28299,7 @@ var publishArtifactInputSchema = external_exports.object({
|
|
|
28268
28299
|
"Optional UTF-8 source used to generate a PDF. When configured, ArtifactPass verifies it against the PDF and signs the agent-readable representation."
|
|
28269
28300
|
),
|
|
28270
28301
|
expires_in_seconds: external_exports.number().int().positive().default(3600).describe(
|
|
28271
|
-
"Deployment expiry preset in seconds. Defaults to one hour (3600).
|
|
28302
|
+
"Deployment expiry preset in seconds. Defaults to one hour (3600). Public ArtifactPass presets: 900, 1800, or 3600; a rejection reports the deployment's allowed values."
|
|
28272
28303
|
)
|
|
28273
28304
|
});
|
|
28274
28305
|
var publishArtifactOutputSchema = external_exports.object({
|
|
@@ -28279,7 +28310,9 @@ var publishArtifactOutputSchema = external_exports.object({
|
|
|
28279
28310
|
var readArtifactInputSchema = external_exports.object({
|
|
28280
28311
|
share_url: external_exports.string().url(),
|
|
28281
28312
|
cursor: external_exports.string().optional(),
|
|
28282
|
-
max_bytes: external_exports.number().int().positive().optional()
|
|
28313
|
+
max_bytes: external_exports.number().int().positive().max(PROTOCOL_MAX_SOURCE_CHUNK_BYTES).optional().describe(
|
|
28314
|
+
`Maximum source bytes per call. Defaults to ${PROTOCOL_MAX_SOURCE_CHUNK_BYTES}.`
|
|
28315
|
+
),
|
|
28283
28316
|
representation: external_exports.enum(["auto", "source", "derived"]).optional()
|
|
28284
28317
|
});
|
|
28285
28318
|
var readArtifactOutputSchema = external_exports.object({
|
|
@@ -28454,11 +28487,34 @@ var deploymentPlan = (input) => {
|
|
|
28454
28487
|
if (!workersSubdomainPattern.test(input.workersSubdomain)) {
|
|
28455
28488
|
throw new Error("Choose a valid Workers account subdomain");
|
|
28456
28489
|
}
|
|
28457
|
-
if (input.identities.length === 0)
|
|
28490
|
+
if (input.publicAuth === void 0 && input.identities.length === 0) {
|
|
28491
|
+
throw new Error("At least one allowed identity is required");
|
|
28492
|
+
}
|
|
28493
|
+
if (input.publicAuth !== void 0 && input.identities.length > 0) {
|
|
28494
|
+
throw new Error("Public ArtifactPass authentication cannot include Cloudflare Access identities");
|
|
28495
|
+
}
|
|
28458
28496
|
for (const identity of input.identities) {
|
|
28459
28497
|
const valid = identity.kind === "email" ? /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/u.test(identity.value) : hostnamePattern.test(`x.${identity.value}`);
|
|
28460
28498
|
if (!valid) throw new Error(`Allowed ${identity.kind} is invalid`);
|
|
28461
28499
|
}
|
|
28500
|
+
if (input.publicAuth !== void 0) {
|
|
28501
|
+
for (const [name, credential] of Object.entries(input.publicAuth)) {
|
|
28502
|
+
if (credential.trim().length === 0 || credential.length > 512) {
|
|
28503
|
+
throw new Error(`${name} must be a non-empty OAuth credential`);
|
|
28504
|
+
}
|
|
28505
|
+
}
|
|
28506
|
+
}
|
|
28507
|
+
if (input.publicAuth !== void 0) {
|
|
28508
|
+
return [
|
|
28509
|
+
"verify the short-lived Cloudflare API token, selected zone, and Workers account subdomain",
|
|
28510
|
+
"reuse or create the private D1 database and R2 bucket",
|
|
28511
|
+
"prepare the public Worker configuration with Google and GitHub OAuth secrets",
|
|
28512
|
+
"apply D1 migrations and the R2 cleanup lifecycle",
|
|
28513
|
+
"deploy the Worker and verify ArtifactPass authentication before removing the old Access gate",
|
|
28514
|
+
"verify public sign-in, protected upload redirection, and health",
|
|
28515
|
+
"print the public connection command without persisting provisioning credentials"
|
|
28516
|
+
];
|
|
28517
|
+
}
|
|
28462
28518
|
return [
|
|
28463
28519
|
"verify the short-lived Cloudflare API token, selected zone, and Workers account subdomain",
|
|
28464
28520
|
"reuse or create the private D1 database and R2 bucket",
|
|
@@ -28475,6 +28531,34 @@ var expectedDestinations = (hostname3) => [
|
|
|
28475
28531
|
];
|
|
28476
28532
|
var identityIncludes = (identities) => identities.map((identity) => identity.kind === "email" ? { email: { email: identity.value } } : { email_domain: { domain: identity.value } });
|
|
28477
28533
|
var canonicalJson = (value2) => JSON.stringify([...value2].sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right))));
|
|
28534
|
+
var restoreLegacyAccess = async (input, serviceName, policies, dependencies) => {
|
|
28535
|
+
const restored = await dependencies.client.request(
|
|
28536
|
+
`/accounts/${input.accountId}/access/apps`,
|
|
28537
|
+
{
|
|
28538
|
+
method: "POST",
|
|
28539
|
+
body: JSON.stringify({
|
|
28540
|
+
name: serviceName,
|
|
28541
|
+
type: "self_hosted",
|
|
28542
|
+
session_duration: "24h",
|
|
28543
|
+
destinations: expectedDestinations(input.hostname)
|
|
28544
|
+
})
|
|
28545
|
+
}
|
|
28546
|
+
);
|
|
28547
|
+
for (const policy of policies) {
|
|
28548
|
+
await dependencies.client.request(
|
|
28549
|
+
`/accounts/${input.accountId}/access/apps/${restored.id}/policies`,
|
|
28550
|
+
{
|
|
28551
|
+
method: "POST",
|
|
28552
|
+
body: JSON.stringify({
|
|
28553
|
+
name: policy.name,
|
|
28554
|
+
decision: policy.decision ?? "allow",
|
|
28555
|
+
include: policy.include ?? []
|
|
28556
|
+
})
|
|
28557
|
+
}
|
|
28558
|
+
);
|
|
28559
|
+
}
|
|
28560
|
+
return restored;
|
|
28561
|
+
};
|
|
28478
28562
|
var deploymentFiles = async (root, directory = root) => {
|
|
28479
28563
|
const entries = await readdir(directory);
|
|
28480
28564
|
const files = [];
|
|
@@ -28545,7 +28629,14 @@ var approvalBinding = async (input, serviceName, dependencies) => {
|
|
|
28545
28629
|
serviceName,
|
|
28546
28630
|
pdfKeyId: input.pdfKeyId,
|
|
28547
28631
|
pdfPublicKeySha256: createHash("sha256").update(input.pdfPublicKey).digest("hex"),
|
|
28548
|
-
workersSubdomain: input.workersSubdomain
|
|
28632
|
+
workersSubdomain: input.workersSubdomain,
|
|
28633
|
+
authMode: input.publicAuth === void 0 ? "cloudflare-access" : "artifactpass",
|
|
28634
|
+
...input.publicAuth === void 0 ? {} : {
|
|
28635
|
+
googleClientId: input.publicAuth.googleClientId,
|
|
28636
|
+
googleClientSecretSha256: createHash("sha256").update(input.publicAuth.googleClientSecret).digest("hex"),
|
|
28637
|
+
githubClientId: input.publicAuth.githubClientId,
|
|
28638
|
+
githubClientSecretSha256: createHash("sha256").update(input.publicAuth.githubClientSecret).digest("hex")
|
|
28639
|
+
}
|
|
28549
28640
|
},
|
|
28550
28641
|
bundleSha256: await deploymentSha256(dependencies.deploymentRoot),
|
|
28551
28642
|
remote: {
|
|
@@ -28564,7 +28655,7 @@ var approvalBinding = async (input, serviceName, dependencies) => {
|
|
|
28564
28655
|
};
|
|
28565
28656
|
};
|
|
28566
28657
|
var readinessRetryDelays = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
28567
|
-
var fetchAfterDeploymentPropagation = async (fetchImplementation, request, init, sleep2, timeoutMilliseconds) => {
|
|
28658
|
+
var fetchAfterDeploymentPropagation = async (fetchImplementation, request, init, sleep2, timeoutMilliseconds, isReady = (response) => response.status !== 404 && response.status !== 429 && response.status < 500) => {
|
|
28568
28659
|
let lastError;
|
|
28569
28660
|
for (let attempt = 0; attempt <= readinessRetryDelays.length; attempt += 1) {
|
|
28570
28661
|
try {
|
|
@@ -28572,7 +28663,7 @@ var fetchAfterDeploymentPropagation = async (fetchImplementation, request, init,
|
|
|
28572
28663
|
...init,
|
|
28573
28664
|
signal: AbortSignal.timeout(timeoutMilliseconds)
|
|
28574
28665
|
});
|
|
28575
|
-
if (
|
|
28666
|
+
if (await isReady(response.clone())) return response;
|
|
28576
28667
|
lastError = new Error(`Deployment route is not ready (${response.status})`);
|
|
28577
28668
|
} catch (error51) {
|
|
28578
28669
|
lastError = error51;
|
|
@@ -28583,6 +28674,17 @@ var fetchAfterDeploymentPropagation = async (fetchImplementation, request, init,
|
|
|
28583
28674
|
}
|
|
28584
28675
|
throw lastError;
|
|
28585
28676
|
};
|
|
28677
|
+
var isArtifactPassUploadRedirect = (response, baseUrl) => {
|
|
28678
|
+
if (response.status !== 302) return false;
|
|
28679
|
+
const location = response.headers.get("location");
|
|
28680
|
+
if (location === null) return false;
|
|
28681
|
+
try {
|
|
28682
|
+
const signInRedirect = new URL(location, baseUrl);
|
|
28683
|
+
return signInRedirect.origin === baseUrl && signInRedirect.pathname === "/auth/sign-in" && signInRedirect.searchParams.get("return_to") === "/upload";
|
|
28684
|
+
} catch {
|
|
28685
|
+
return false;
|
|
28686
|
+
}
|
|
28687
|
+
};
|
|
28586
28688
|
var deployArtifactShare = async (input, dependencies) => {
|
|
28587
28689
|
const plan = deploymentPlan(input);
|
|
28588
28690
|
const serviceName = input.serviceName ?? "lordebuilds-artifacts-share";
|
|
@@ -28597,7 +28699,7 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28597
28699
|
const binding = await approvalBinding(input, serviceName, dependencies);
|
|
28598
28700
|
if (input.writeApprovalManifest !== void 0) {
|
|
28599
28701
|
const manifest = {
|
|
28600
|
-
version:
|
|
28702
|
+
version: 2,
|
|
28601
28703
|
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
28602
28704
|
binding
|
|
28603
28705
|
};
|
|
@@ -28612,7 +28714,7 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28612
28714
|
};
|
|
28613
28715
|
}
|
|
28614
28716
|
const approved = JSON.parse(await readFile2(input.approveManifest ?? "", "utf8"));
|
|
28615
|
-
if (approved.version !==
|
|
28717
|
+
if (approved.version !== 2 || JSON.stringify(approved.binding) !== JSON.stringify(binding)) {
|
|
28616
28718
|
throw new Error("Hosted approval manifest no longer matches the deployment bundle or Cloudflare state");
|
|
28617
28719
|
}
|
|
28618
28720
|
}
|
|
@@ -28666,7 +28768,18 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28666
28768
|
`/accounts/${input.accountId}/access/apps`
|
|
28667
28769
|
);
|
|
28668
28770
|
let application = applications.find((candidate) => candidate.name === serviceName);
|
|
28669
|
-
|
|
28771
|
+
const legacyAccessPolicies = input.publicAuth !== void 0 && application !== void 0 ? await dependencies.client.request(
|
|
28772
|
+
`/accounts/${input.accountId}/access/apps/${application.id}/policies`
|
|
28773
|
+
) : [];
|
|
28774
|
+
if (input.publicAuth !== void 0 && application !== void 0) {
|
|
28775
|
+
const actual = canonicalJson((application.destinations ?? []).map((destination) => ({
|
|
28776
|
+
type: destination.type,
|
|
28777
|
+
...destination.uri === void 0 ? {} : { uri: destination.uri }
|
|
28778
|
+
})));
|
|
28779
|
+
if (actual !== canonicalJson(expectedDestinations(input.hostname))) {
|
|
28780
|
+
throw new Error("Existing Access application has different protected paths and cannot be removed safely");
|
|
28781
|
+
}
|
|
28782
|
+
} else if (input.publicAuth === void 0 && application === void 0) {
|
|
28670
28783
|
application = await dependencies.client.request(
|
|
28671
28784
|
`/accounts/${input.accountId}/access/apps`,
|
|
28672
28785
|
{
|
|
@@ -28680,7 +28793,8 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28680
28793
|
}
|
|
28681
28794
|
);
|
|
28682
28795
|
changed.push("Access application");
|
|
28683
|
-
} else {
|
|
28796
|
+
} else if (input.publicAuth === void 0) {
|
|
28797
|
+
if (application === void 0) throw new Error("Cloudflare Access application is unavailable");
|
|
28684
28798
|
const actual = canonicalJson((application.destinations ?? []).map((destination) => ({
|
|
28685
28799
|
type: destination.type,
|
|
28686
28800
|
...destination.uri === void 0 ? {} : { uri: destination.uri }
|
|
@@ -28689,43 +28803,46 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28689
28803
|
throw new Error("Existing Access application has different protected paths");
|
|
28690
28804
|
}
|
|
28691
28805
|
}
|
|
28692
|
-
if (
|
|
28693
|
-
throw new Error("Cloudflare Access application
|
|
28694
|
-
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
|
|
28702
|
-
const policy = policies.find((candidate) => candidate.name === "Artifact Share uploaders");
|
|
28703
|
-
if (policy === void 0) {
|
|
28704
|
-
await dependencies.client.request(
|
|
28705
|
-
`/accounts/${input.accountId}/access/apps/${application.id}/policies`,
|
|
28706
|
-
{
|
|
28707
|
-
method: "POST",
|
|
28708
|
-
body: JSON.stringify({
|
|
28709
|
-
name: "Artifact Share uploaders",
|
|
28710
|
-
decision: "allow",
|
|
28711
|
-
include: expectedIncludes
|
|
28712
|
-
})
|
|
28713
|
-
}
|
|
28714
|
-
);
|
|
28715
|
-
changed.push("Access policy");
|
|
28716
|
-
} else if (policy.decision !== "allow" || canonicalJson(policy.include ?? []) !== canonicalJson(expectedIncludes)) {
|
|
28717
|
-
await dependencies.client.request(
|
|
28718
|
-
`/accounts/${input.accountId}/access/apps/${application.id}/policies/${policy.id}`,
|
|
28719
|
-
{
|
|
28720
|
-
method: "PUT",
|
|
28721
|
-
body: JSON.stringify({
|
|
28722
|
-
name: "Artifact Share uploaders",
|
|
28723
|
-
decision: "allow",
|
|
28724
|
-
include: expectedIncludes
|
|
28725
|
-
})
|
|
28726
|
-
}
|
|
28806
|
+
if (input.publicAuth === void 0) {
|
|
28807
|
+
if (application === void 0) throw new Error("Cloudflare Access application is unavailable");
|
|
28808
|
+
if (typeof application.aud !== "string" || application.aud.length === 0) {
|
|
28809
|
+
throw new Error("Cloudflare Access application did not return an audience tag");
|
|
28810
|
+
}
|
|
28811
|
+
if (!/^[a-z0-9-]+\.cloudflareaccess\.com$/u.test(organization.auth_domain)) {
|
|
28812
|
+
throw new Error("Cloudflare Access organization returned an invalid team domain");
|
|
28813
|
+
}
|
|
28814
|
+
const policies = await dependencies.client.request(
|
|
28815
|
+
`/accounts/${input.accountId}/access/apps/${application.id}/policies`
|
|
28727
28816
|
);
|
|
28728
|
-
|
|
28817
|
+
const expectedIncludes = identityIncludes(input.identities);
|
|
28818
|
+
const policy = policies.find((candidate) => candidate.name === "Artifact Share uploaders");
|
|
28819
|
+
if (policy === void 0) {
|
|
28820
|
+
await dependencies.client.request(
|
|
28821
|
+
`/accounts/${input.accountId}/access/apps/${application.id}/policies`,
|
|
28822
|
+
{
|
|
28823
|
+
method: "POST",
|
|
28824
|
+
body: JSON.stringify({
|
|
28825
|
+
name: "Artifact Share uploaders",
|
|
28826
|
+
decision: "allow",
|
|
28827
|
+
include: expectedIncludes
|
|
28828
|
+
})
|
|
28829
|
+
}
|
|
28830
|
+
);
|
|
28831
|
+
changed.push("Access policy");
|
|
28832
|
+
} else if (policy.decision !== "allow" || canonicalJson(policy.include ?? []) !== canonicalJson(expectedIncludes)) {
|
|
28833
|
+
await dependencies.client.request(
|
|
28834
|
+
`/accounts/${input.accountId}/access/apps/${application.id}/policies/${policy.id}`,
|
|
28835
|
+
{
|
|
28836
|
+
method: "PUT",
|
|
28837
|
+
body: JSON.stringify({
|
|
28838
|
+
name: "Artifact Share uploaders",
|
|
28839
|
+
decision: "allow",
|
|
28840
|
+
include: expectedIncludes
|
|
28841
|
+
})
|
|
28842
|
+
}
|
|
28843
|
+
);
|
|
28844
|
+
changed.push("Access policy");
|
|
28845
|
+
}
|
|
28729
28846
|
}
|
|
28730
28847
|
const template = JSON.parse(await readFile2(resolve3(dependencies.deploymentRoot, "wrangler-template.json"), "utf8"));
|
|
28731
28848
|
template.name = serviceName;
|
|
@@ -28741,8 +28858,24 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28741
28858
|
template.routes = [{ pattern: input.hostname, custom_domain: true }];
|
|
28742
28859
|
template.workers_dev = false;
|
|
28743
28860
|
template.preview_urls = false;
|
|
28744
|
-
|
|
28745
|
-
|
|
28861
|
+
if (input.publicAuth === void 0) {
|
|
28862
|
+
if (application === void 0) throw new Error("Cloudflare Access application is unavailable");
|
|
28863
|
+
delete template.secrets;
|
|
28864
|
+
template.vars.HUMAN_AUTH_MODE = "cloudflare-access";
|
|
28865
|
+
template.vars.ACCESS_TEAM_DOMAIN = `https://${organization.auth_domain}`;
|
|
28866
|
+
template.vars.ACCESS_AUD = application.aud;
|
|
28867
|
+
} else {
|
|
28868
|
+
template.secrets = {
|
|
28869
|
+
required: ["GOOGLE_OAUTH_CLIENT_SECRET", "GITHUB_OAUTH_CLIENT_SECRET"]
|
|
28870
|
+
};
|
|
28871
|
+
delete template.vars.ACCESS_TEAM_DOMAIN;
|
|
28872
|
+
delete template.vars.ACCESS_AUD;
|
|
28873
|
+
template.vars.HUMAN_AUTH_MODE = "artifactpass";
|
|
28874
|
+
template.vars.GOOGLE_OAUTH_CLIENT_ID = input.publicAuth.googleClientId;
|
|
28875
|
+
template.vars.GITHUB_OAUTH_CLIENT_ID = input.publicAuth.githubClientId;
|
|
28876
|
+
template.vars.ALLOWED_EXPIRY_SECONDS = "900,1800,3600";
|
|
28877
|
+
template.vars.MAX_EXPIRY_SECONDS = "3600";
|
|
28878
|
+
}
|
|
28746
28879
|
template.vars.PDF_PROVENANCE_KEY_ID = input.pdfKeyId;
|
|
28747
28880
|
template.vars.PDF_PROVENANCE_PUBLIC_KEYS = JSON.stringify({ [input.pdfKeyId]: input.pdfPublicKey });
|
|
28748
28881
|
template.vars.PDF_PROVENANCE_RENDERERS = "artifact-share-qualified-pdf@1";
|
|
@@ -28770,6 +28903,15 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28770
28903
|
resolve3(dependencies.deploymentRoot, "storage-lifecycle.json"),
|
|
28771
28904
|
"--force"
|
|
28772
28905
|
], { env: commandEnvironment });
|
|
28906
|
+
if (input.publicAuth !== void 0) {
|
|
28907
|
+
await runner("wrangler", ["secret", "bulk", "--config", configurationPath], {
|
|
28908
|
+
env: commandEnvironment,
|
|
28909
|
+
input: JSON.stringify({
|
|
28910
|
+
GOOGLE_OAUTH_CLIENT_SECRET: input.publicAuth.googleClientSecret,
|
|
28911
|
+
GITHUB_OAUTH_CLIENT_SECRET: input.publicAuth.githubClientSecret
|
|
28912
|
+
})
|
|
28913
|
+
});
|
|
28914
|
+
}
|
|
28773
28915
|
await runner("wrangler", ["deploy", "--config", configurationPath, "--strict"], { env: commandEnvironment });
|
|
28774
28916
|
changed.push("Worker deployment");
|
|
28775
28917
|
} finally {
|
|
@@ -28778,16 +28920,113 @@ var deployArtifactShare = async (input, dependencies) => {
|
|
|
28778
28920
|
const fetchImplementation = dependencies.fetch ?? globalThis.fetch;
|
|
28779
28921
|
const sleep2 = dependencies.sleep ?? (async (milliseconds) => await new Promise((resolveSleep) => setTimeout(resolveSleep, milliseconds)));
|
|
28780
28922
|
const readinessTimeoutMilliseconds = dependencies.readinessTimeoutMilliseconds ?? 1e4;
|
|
28781
|
-
|
|
28923
|
+
await fetchAfterDeploymentPropagation(
|
|
28782
28924
|
fetchImplementation,
|
|
28783
28925
|
`${baseUrl}/health`,
|
|
28784
28926
|
{ redirect: "error" },
|
|
28785
28927
|
sleep2,
|
|
28786
|
-
readinessTimeoutMilliseconds
|
|
28928
|
+
readinessTimeoutMilliseconds,
|
|
28929
|
+
async (candidate) => {
|
|
28930
|
+
if (!candidate.ok) return false;
|
|
28931
|
+
const candidateHealth = await candidate.json().catch(() => null);
|
|
28932
|
+
if (candidateHealth?.service !== "lordebuilds.artifacts.share" || candidateHealth.status !== "ok") {
|
|
28933
|
+
return false;
|
|
28934
|
+
}
|
|
28935
|
+
return input.publicAuth === void 0 || candidateHealth.human_auth_mode === "artifactpass" && candidateHealth.authentication_configured === true;
|
|
28936
|
+
}
|
|
28787
28937
|
);
|
|
28788
|
-
|
|
28789
|
-
|
|
28790
|
-
|
|
28938
|
+
if (input.publicAuth !== void 0) {
|
|
28939
|
+
const signIn = await fetchAfterDeploymentPropagation(
|
|
28940
|
+
fetchImplementation,
|
|
28941
|
+
`${baseUrl}/auth/sign-in?return_to=%2Fupload`,
|
|
28942
|
+
{ redirect: "manual" },
|
|
28943
|
+
sleep2,
|
|
28944
|
+
readinessTimeoutMilliseconds
|
|
28945
|
+
);
|
|
28946
|
+
if (!signIn.ok || !(await signIn.text()).includes("Continue with Google")) {
|
|
28947
|
+
throw new Error(`ArtifactPass sign-in check failed (${signIn.status})`);
|
|
28948
|
+
}
|
|
28949
|
+
for (const provider of ["google", "github"]) {
|
|
28950
|
+
const login = await fetchAfterDeploymentPropagation(
|
|
28951
|
+
fetchImplementation,
|
|
28952
|
+
`${baseUrl}/auth/login/${provider}?return_to=%2Fupload`,
|
|
28953
|
+
{ redirect: "manual" },
|
|
28954
|
+
sleep2,
|
|
28955
|
+
readinessTimeoutMilliseconds
|
|
28956
|
+
);
|
|
28957
|
+
const location = login.headers.get("location");
|
|
28958
|
+
const expectedOrigin = provider === "google" ? "https://accounts.google.com" : "https://github.com";
|
|
28959
|
+
if (login.status !== 302 || location === null || new URL(location).origin !== expectedOrigin) {
|
|
28960
|
+
throw new Error(`ArtifactPass ${provider} authentication check failed (${login.status})`);
|
|
28961
|
+
}
|
|
28962
|
+
}
|
|
28963
|
+
let removedLegacyAccess = false;
|
|
28964
|
+
if (application !== void 0) {
|
|
28965
|
+
await dependencies.client.request(
|
|
28966
|
+
`/accounts/${input.accountId}/access/apps/${application.id}`,
|
|
28967
|
+
{ method: "DELETE" }
|
|
28968
|
+
);
|
|
28969
|
+
removedLegacyAccess = true;
|
|
28970
|
+
changed.push("Access application removal");
|
|
28971
|
+
}
|
|
28972
|
+
try {
|
|
28973
|
+
await fetchAfterDeploymentPropagation(
|
|
28974
|
+
fetchImplementation,
|
|
28975
|
+
`${baseUrl}/upload`,
|
|
28976
|
+
{ redirect: "manual" },
|
|
28977
|
+
sleep2,
|
|
28978
|
+
readinessTimeoutMilliseconds,
|
|
28979
|
+
(candidate) => isArtifactPassUploadRedirect(candidate, baseUrl)
|
|
28980
|
+
);
|
|
28981
|
+
} catch (error51) {
|
|
28982
|
+
if (removedLegacyAccess) {
|
|
28983
|
+
try {
|
|
28984
|
+
const restoredApplication = await restoreLegacyAccess(
|
|
28985
|
+
input,
|
|
28986
|
+
serviceName,
|
|
28987
|
+
legacyAccessPolicies,
|
|
28988
|
+
dependencies
|
|
28989
|
+
);
|
|
28990
|
+
if (typeof restoredApplication.aud !== "string" || restoredApplication.aud.length === 0 || !/^[a-z0-9-]+\.cloudflareaccess\.com$/u.test(organization.auth_domain)) {
|
|
28991
|
+
throw new Error("Restored Cloudflare Access configuration is incomplete");
|
|
28992
|
+
}
|
|
28993
|
+
const rollbackTemplate = structuredClone(template);
|
|
28994
|
+
delete rollbackTemplate.secrets;
|
|
28995
|
+
rollbackTemplate.vars.HUMAN_AUTH_MODE = "cloudflare-access";
|
|
28996
|
+
rollbackTemplate.vars.ACCESS_TEAM_DOMAIN = `https://${organization.auth_domain}`;
|
|
28997
|
+
rollbackTemplate.vars.ACCESS_AUD = restoredApplication.aud;
|
|
28998
|
+
delete rollbackTemplate.vars.GOOGLE_OAUTH_CLIENT_ID;
|
|
28999
|
+
delete rollbackTemplate.vars.GITHUB_OAUTH_CLIENT_ID;
|
|
29000
|
+
const rollbackRoot = await mkdtemp(resolve3(tmpdir(), "artifact-share-rollback-"));
|
|
29001
|
+
try {
|
|
29002
|
+
const rollbackConfigurationPath = resolve3(rollbackRoot, "wrangler.json");
|
|
29003
|
+
await writeFile2(rollbackConfigurationPath, JSON.stringify(rollbackTemplate), { mode: 384 });
|
|
29004
|
+
await runner("wrangler", ["deploy", "--config", rollbackConfigurationPath, "--strict"], {
|
|
29005
|
+
env: { CLOUDFLARE_ACCOUNT_ID: input.accountId }
|
|
29006
|
+
});
|
|
29007
|
+
} finally {
|
|
29008
|
+
await rm(rollbackRoot, { recursive: true });
|
|
29009
|
+
}
|
|
29010
|
+
await fetchAfterDeploymentPropagation(
|
|
29011
|
+
fetchImplementation,
|
|
29012
|
+
`${baseUrl}/upload`,
|
|
29013
|
+
{ redirect: "manual" },
|
|
29014
|
+
sleep2,
|
|
29015
|
+
readinessTimeoutMilliseconds,
|
|
29016
|
+
(candidate) => [302, 303, 307, 401, 403].includes(candidate.status)
|
|
29017
|
+
);
|
|
29018
|
+
} catch (restoreError) {
|
|
29019
|
+
throw new AggregateError(
|
|
29020
|
+
[error51, restoreError],
|
|
29021
|
+
"ArtifactPass upload verification failed and the legacy Access gate could not be restored"
|
|
29022
|
+
);
|
|
29023
|
+
}
|
|
29024
|
+
}
|
|
29025
|
+
throw new Error("ArtifactPass did not protect the upload route after deployment propagation", {
|
|
29026
|
+
cause: error51
|
|
29027
|
+
});
|
|
29028
|
+
}
|
|
29029
|
+
return { baseUrl, teamCommand, plan, changed };
|
|
28791
29030
|
}
|
|
28792
29031
|
const protectedUpload = await fetchAfterDeploymentPropagation(
|
|
28793
29032
|
fetchImplementation,
|
|
@@ -28956,7 +29195,7 @@ var claudePluginEntries = (value2) => {
|
|
|
28956
29195
|
}
|
|
28957
29196
|
return value2;
|
|
28958
29197
|
};
|
|
28959
|
-
var installPluginForHosts = async (hosts, marketplaceSource, runner = runProcess) => {
|
|
29198
|
+
var installPluginForHosts = async (hosts, marketplaceSource, binding, runner = runProcess) => {
|
|
28960
29199
|
const rollbackActions = [];
|
|
28961
29200
|
const rollback = async () => {
|
|
28962
29201
|
const errors = [];
|
|
@@ -28993,6 +29232,21 @@ var installPluginForHosts = async (hosts, marketplaceSource, runner = runProcess
|
|
|
28993
29232
|
if (hadPlugin) await runner("codex", ["plugin", "add", artifactpassPluginId, "--json"]);
|
|
28994
29233
|
});
|
|
28995
29234
|
await runner("codex", ["plugin", "add", artifactpassPluginId, "--json"]);
|
|
29235
|
+
await runner("codex", [
|
|
29236
|
+
"mcp",
|
|
29237
|
+
"add",
|
|
29238
|
+
"artifactpass",
|
|
29239
|
+
"--env",
|
|
29240
|
+
`ARTIFACTPASS_CONFIG_PATH=${binding.configPath}`,
|
|
29241
|
+
"--env",
|
|
29242
|
+
`ARTIFACTPASS_PROFILE=${binding.profileName}`,
|
|
29243
|
+
"--",
|
|
29244
|
+
process.execPath,
|
|
29245
|
+
binding.bridgePath
|
|
29246
|
+
]);
|
|
29247
|
+
rollbackActions.push(async () => {
|
|
29248
|
+
await runner("codex", ["mcp", "remove", "artifactpass"]);
|
|
29249
|
+
});
|
|
28996
29250
|
}
|
|
28997
29251
|
if (hosts.includes("claude")) {
|
|
28998
29252
|
const marketplaces = namedEntries(parseJson(
|
|
@@ -29039,6 +29293,23 @@ var installPluginForHosts = async (hosts, marketplaceSource, runner = runProcess
|
|
|
29039
29293
|
"--scope",
|
|
29040
29294
|
"user"
|
|
29041
29295
|
]);
|
|
29296
|
+
await runner("claude", [
|
|
29297
|
+
"mcp",
|
|
29298
|
+
"add",
|
|
29299
|
+
"--scope",
|
|
29300
|
+
"user",
|
|
29301
|
+
"artifactpass",
|
|
29302
|
+
"-e",
|
|
29303
|
+
`ARTIFACTPASS_CONFIG_PATH=${binding.configPath}`,
|
|
29304
|
+
"-e",
|
|
29305
|
+
`ARTIFACTPASS_PROFILE=${binding.profileName}`,
|
|
29306
|
+
"--",
|
|
29307
|
+
process.execPath,
|
|
29308
|
+
binding.bridgePath
|
|
29309
|
+
]);
|
|
29310
|
+
rollbackActions.push(async () => {
|
|
29311
|
+
await runner("claude", ["mcp", "remove", "artifactpass", "--scope", "user"]);
|
|
29312
|
+
});
|
|
29042
29313
|
}
|
|
29043
29314
|
return { hosts, rollback };
|
|
29044
29315
|
} catch (error51) {
|
|
@@ -29482,7 +29753,16 @@ var connectHost = async (input, dependencies) => {
|
|
|
29482
29753
|
sourceRoot: resolve5(input.marketplaceSource, "plugins/artifactpass")
|
|
29483
29754
|
}) : void 0;
|
|
29484
29755
|
const installAndVerify = async () => {
|
|
29485
|
-
const hostInstallation = installKnownHostAdapters && hosts.length > 0 ? await installPluginForHosts(hosts, input.marketplaceSource,
|
|
29756
|
+
const hostInstallation = installKnownHostAdapters && hosts.length > 0 ? await installPluginForHosts(hosts, input.marketplaceSource, {
|
|
29757
|
+
configPath,
|
|
29758
|
+
profileName,
|
|
29759
|
+
bridgePath: resolve5(
|
|
29760
|
+
input.hostBridgePath ?? resolve5(
|
|
29761
|
+
input.marketplaceSource,
|
|
29762
|
+
"plugins/artifactpass/dist/cli.mjs"
|
|
29763
|
+
)
|
|
29764
|
+
)
|
|
29765
|
+
}, runner) : void 0;
|
|
29486
29766
|
try {
|
|
29487
29767
|
await dependencies.verifyConnection?.({
|
|
29488
29768
|
configPath,
|
|
@@ -29532,15 +29812,26 @@ var connectHost = async (input, dependencies) => {
|
|
|
29532
29812
|
...migration === void 0 ? {} : { migration }
|
|
29533
29813
|
};
|
|
29534
29814
|
}
|
|
29535
|
-
const
|
|
29536
|
-
if (
|
|
29815
|
+
const previousStoredCredential = await store.get();
|
|
29816
|
+
if (previousStoredCredential !== null && previousProfile === void 0) {
|
|
29537
29817
|
throw new Error(`The existing ArtifactPass ${profileName} credential has no matching profile; disconnect it first`);
|
|
29538
29818
|
}
|
|
29539
|
-
|
|
29819
|
+
const previousToken = previousStoredCredential === null || previousProfile === void 0 ? null : resolveAgentCredential(
|
|
29820
|
+
previousStoredCredential,
|
|
29821
|
+
previousProfile.base_url,
|
|
29822
|
+
previousProfile.credential_binding === "origin"
|
|
29823
|
+
);
|
|
29824
|
+
if (previousToken !== null && previousProfile !== void 0 && previousProfile.open_development !== true && new URL(previousProfile.base_url).origin === origin.origin) {
|
|
29540
29825
|
const inspection = await inspectToken(origin, previousToken, fetchImplementation);
|
|
29541
29826
|
if (inspection !== null) {
|
|
29542
29827
|
if (previousSettings === null) throw new Error("ArtifactPass profile state disappeared");
|
|
29828
|
+
const boundCredential = bindAgentCredential(origin, previousToken);
|
|
29829
|
+
let migratedCredential = false;
|
|
29543
29830
|
try {
|
|
29831
|
+
if (boundCredential !== previousStoredCredential) {
|
|
29832
|
+
await store.set(boundCredential);
|
|
29833
|
+
migratedCredential = true;
|
|
29834
|
+
}
|
|
29544
29835
|
await (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, upsertLocalBridgeProfile(
|
|
29545
29836
|
previousSettings,
|
|
29546
29837
|
profileName,
|
|
@@ -29550,11 +29841,13 @@ var connectHost = async (input, dependencies) => {
|
|
|
29550
29841
|
...previousProfile.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
29551
29842
|
...previousProfile.publication_state_path === void 0 ? {} : { publication_state_path: previousProfile.publication_state_path },
|
|
29552
29843
|
credential_namespace: "artifactpass",
|
|
29844
|
+
credential_binding: "origin",
|
|
29553
29845
|
...healthBody.pdf_provenance_key_id === void 0 ? previousProfile.pdf_key_id === void 0 ? {} : { pdf_key_id: previousProfile.pdf_key_id } : { pdf_key_id: healthBody.pdf_provenance_key_id }
|
|
29554
29846
|
}
|
|
29555
29847
|
));
|
|
29556
29848
|
await installAndVerify();
|
|
29557
29849
|
} catch (error51) {
|
|
29850
|
+
if (migratedCredential) await store.set(previousStoredCredential);
|
|
29558
29851
|
await (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, previousSettings).catch((rollbackError) => {
|
|
29559
29852
|
throw new AggregateError([error51, rollbackError], "ArtifactPass connection verification failed and config rollback was incomplete");
|
|
29560
29853
|
});
|
|
@@ -29587,11 +29880,12 @@ var connectHost = async (input, dependencies) => {
|
|
|
29587
29880
|
...previousProfile?.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
29588
29881
|
...previousProfile?.publication_state_path === void 0 ? {} : { publication_state_path: previousProfile.publication_state_path },
|
|
29589
29882
|
credential_namespace: "artifactpass",
|
|
29883
|
+
credential_binding: "origin",
|
|
29590
29884
|
...healthBody.pdf_provenance_key_id === void 0 ? {} : { pdf_key_id: healthBody.pdf_provenance_key_id }
|
|
29591
29885
|
}
|
|
29592
29886
|
));
|
|
29593
29887
|
wroteConfig = true;
|
|
29594
|
-
await store.set(token.accessToken);
|
|
29888
|
+
await store.set(bindAgentCredential(origin, token.accessToken));
|
|
29595
29889
|
rollbackHostInstallation = await installAndVerify();
|
|
29596
29890
|
if (previousToken !== null && previousProfile !== void 0 && previousProfile.open_development !== true) {
|
|
29597
29891
|
await revokeToken(
|
|
@@ -29608,10 +29902,10 @@ var connectHost = async (input, dependencies) => {
|
|
|
29608
29902
|
await revokeToken(origin, token.accessToken, fetchImplementation).catch((cleanupError) => {
|
|
29609
29903
|
cleanupErrors.push(cleanupError);
|
|
29610
29904
|
});
|
|
29611
|
-
if (
|
|
29905
|
+
if (previousStoredCredential === null) {
|
|
29612
29906
|
await store.delete().catch((cleanupError) => cleanupErrors.push(cleanupError));
|
|
29613
29907
|
} else {
|
|
29614
|
-
await store.set(
|
|
29908
|
+
await store.set(previousStoredCredential).catch((cleanupError) => cleanupErrors.push(cleanupError));
|
|
29615
29909
|
}
|
|
29616
29910
|
if (wroteConfig) {
|
|
29617
29911
|
const restoreConfig = previousSettings === null ? rm4(configPath, { force: true }) : (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, previousSettings);
|
|
@@ -29627,7 +29921,7 @@ var connectHost = async (input, dependencies) => {
|
|
|
29627
29921
|
profileName,
|
|
29628
29922
|
expiresIn: token.expiresIn,
|
|
29629
29923
|
configPath,
|
|
29630
|
-
credentialAction:
|
|
29924
|
+
credentialAction: previousStoredCredential === null ? "created" : "rotated",
|
|
29631
29925
|
...portableIntegration === void 0 ? {} : { portableIntegration },
|
|
29632
29926
|
...migration === void 0 ? {} : { migration }
|
|
29633
29927
|
};
|
|
@@ -29663,9 +29957,10 @@ var disconnectHost = async (baseUrl, options = {}) => {
|
|
|
29663
29957
|
}),
|
|
29664
29958
|
migrationCommitted: true
|
|
29665
29959
|
});
|
|
29666
|
-
const
|
|
29667
|
-
if (
|
|
29960
|
+
const storedCredential = await store.get();
|
|
29961
|
+
if (storedCredential === null) return;
|
|
29668
29962
|
const origin = assertSafeDeploymentOrigin(new URL(baseUrl));
|
|
29963
|
+
const token = resolveAgentCredential(storedCredential, origin);
|
|
29669
29964
|
const response = await (options.fetch ?? globalThis.fetch)(new URL("/api/connection", origin), {
|
|
29670
29965
|
method: "DELETE",
|
|
29671
29966
|
headers: { Authorization: `Bearer ${token}` },
|
|
@@ -29677,6 +29972,45 @@ var disconnectHost = async (baseUrl, options = {}) => {
|
|
|
29677
29972
|
await store.delete();
|
|
29678
29973
|
};
|
|
29679
29974
|
|
|
29975
|
+
// src/cli-arguments.ts
|
|
29976
|
+
var CONNECT_VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
29977
|
+
"--profile",
|
|
29978
|
+
"--workspace-root",
|
|
29979
|
+
"--host",
|
|
29980
|
+
"--marketplace"
|
|
29981
|
+
]);
|
|
29982
|
+
var CONNECT_BOOLEAN_OPTIONS = /* @__PURE__ */ new Set([
|
|
29983
|
+
"--no-host-install",
|
|
29984
|
+
"--open-development"
|
|
29985
|
+
]);
|
|
29986
|
+
var parseConnectArguments = (args) => {
|
|
29987
|
+
const positionals = [];
|
|
29988
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
29989
|
+
const argument = args[index] ?? "";
|
|
29990
|
+
if (CONNECT_VALUE_OPTIONS.has(argument)) {
|
|
29991
|
+
const optionValue = args[index + 1];
|
|
29992
|
+
if (optionValue === void 0 || optionValue.startsWith("--")) {
|
|
29993
|
+
throw new Error(`${argument} requires a value`);
|
|
29994
|
+
}
|
|
29995
|
+
index += 1;
|
|
29996
|
+
continue;
|
|
29997
|
+
}
|
|
29998
|
+
if (CONNECT_BOOLEAN_OPTIONS.has(argument)) continue;
|
|
29999
|
+
if (argument.startsWith("--")) throw new Error(`Unknown connect option: ${argument}`);
|
|
30000
|
+
positionals.push(argument);
|
|
30001
|
+
}
|
|
30002
|
+
if (positionals.length > 1) throw new Error("connect accepts at most one deployment URL");
|
|
30003
|
+
return positionals[0] === void 0 ? {} : { deploymentUrl: positionals[0] };
|
|
30004
|
+
};
|
|
30005
|
+
var resolveConnectDeploymentUrl = (parsed, settings, requestedProfile) => {
|
|
30006
|
+
if (parsed.deploymentUrl !== void 0) return parsed.deploymentUrl;
|
|
30007
|
+
if (requestedProfile !== void 0 && settings?.profiles[requestedProfile] === void 0) {
|
|
30008
|
+
throw new Error(`Unknown ArtifactPass profile: ${requestedProfile}; provide its deployment URL to create it`);
|
|
30009
|
+
}
|
|
30010
|
+
const profileName = requestedProfile ?? settings?.active_profile;
|
|
30011
|
+
return (profileName === void 0 ? void 0 : settings?.profiles[profileName]?.base_url) ?? "https://artifactpass.com";
|
|
30012
|
+
};
|
|
30013
|
+
|
|
29680
30014
|
// src/doctor.ts
|
|
29681
30015
|
import { access, constants } from "node:fs/promises";
|
|
29682
30016
|
var commandExists = async (runner, command) => {
|
|
@@ -29726,8 +30060,12 @@ import { dirname as dirname6, join as join2, parse as parse3, resolve as resolve
|
|
|
29726
30060
|
// package.json
|
|
29727
30061
|
var package_default = {
|
|
29728
30062
|
name: "artifactpass",
|
|
29729
|
-
version: "0.1.0-rc.
|
|
30063
|
+
version: "0.1.0-rc.4",
|
|
29730
30064
|
description: "Install and connect ArtifactPass for compatible AI agent systems.",
|
|
30065
|
+
repository: {
|
|
30066
|
+
type: "git",
|
|
30067
|
+
url: "git+https://github.com/lordelogos/lordebuilds.artifact.pass.git"
|
|
30068
|
+
},
|
|
29731
30069
|
type: "module",
|
|
29732
30070
|
bin: {
|
|
29733
30071
|
artifactpass: "dist/cli.mjs"
|
|
@@ -29890,9 +30228,11 @@ var renderInstallReceipt = (receipt) => {
|
|
|
29890
30228
|
return `ArtifactPass installation failed during ${receipt.failed_stage ?? "setup"}. Previous working state was restored.`;
|
|
29891
30229
|
}
|
|
29892
30230
|
const registration = receipt.portable_bundle.host_registration === "manual-required" ? `Manual host registration required. MCP: ${receipt.portable_bundle.mcp_config ?? "unavailable"}; skills: ${receipt.portable_bundle.skills_directory ?? "unavailable"}.` : `Installed for ${receipt.adapters.join(" and ")}.`;
|
|
29893
|
-
|
|
30231
|
+
const connection = receipt.credential === "none" ? `ArtifactPass is installed for ${receipt.profile} but not connected. Run \`pnpm dlx artifactpass connect ${receipt.origin} --profile ${receipt.profile}\` when you want to publish.` : `ArtifactPass is connected to ${receipt.origin} for ${receipt.profile}.`;
|
|
30232
|
+
return `${connection} ${registration} Start a new agent session before using it.`;
|
|
29894
30233
|
};
|
|
29895
30234
|
var runArtifactpassInstall = async (input, dependencies) => {
|
|
30235
|
+
const connectAfterInstall = input.connectAfterInstall === true;
|
|
29896
30236
|
const now = dependencies.now ?? Date.now;
|
|
29897
30237
|
const operationId = (dependencies.operationId ?? randomUUID3)();
|
|
29898
30238
|
const origin = new URL(input.baseUrl ?? "https://artifactpass.com").origin;
|
|
@@ -29913,6 +30253,7 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29913
30253
|
let smoke;
|
|
29914
30254
|
let skills = [];
|
|
29915
30255
|
let connectResult;
|
|
30256
|
+
let hostInstallation;
|
|
29916
30257
|
let configSnapshot;
|
|
29917
30258
|
const outcomes = [];
|
|
29918
30259
|
try {
|
|
@@ -29932,7 +30273,7 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29932
30273
|
if (isMissing(error51)) return { existed: false };
|
|
29933
30274
|
throw error51;
|
|
29934
30275
|
});
|
|
29935
|
-
if (dependencies.skipCredentialStorePreflight !== true && input.openDevelopment !== true) {
|
|
30276
|
+
if (connectAfterInstall && dependencies.skipCredentialStorePreflight !== true && input.openDevelopment !== true) {
|
|
29936
30277
|
await verifyCredentialStore(
|
|
29937
30278
|
dependencies.platform ?? process.platform,
|
|
29938
30279
|
dependencies.runner ?? runProcess
|
|
@@ -29952,24 +30293,74 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29952
30293
|
stage = "connection";
|
|
29953
30294
|
journal = { ...journal, stage };
|
|
29954
30295
|
await writeJson(journalPath, journal);
|
|
29955
|
-
|
|
29956
|
-
|
|
29957
|
-
|
|
29958
|
-
|
|
29959
|
-
|
|
29960
|
-
|
|
29961
|
-
|
|
29962
|
-
|
|
29963
|
-
|
|
29964
|
-
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
29969
|
-
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
30296
|
+
if (connectAfterInstall) {
|
|
30297
|
+
connectResult = await (dependencies.connect ?? connectHost)({
|
|
30298
|
+
baseUrl: origin,
|
|
30299
|
+
profileName,
|
|
30300
|
+
workspaceRoots: [workspaceRoot],
|
|
30301
|
+
marketplaceSource: input.marketplaceSource,
|
|
30302
|
+
hostBridgePath: resolve6(portable.rootDirectory, "plugin/dist/cli.mjs"),
|
|
30303
|
+
openDevelopment: input.openDevelopment === true,
|
|
30304
|
+
installKnownHostAdapters: input.installKnownHostAdapters !== false,
|
|
30305
|
+
...input.configPath === void 0 ? {} : { configPath }
|
|
30306
|
+
}, {
|
|
30307
|
+
...dependencies.connectDependencies,
|
|
30308
|
+
verifyConnection: async (context) => {
|
|
30309
|
+
[smoke, skills] = await Promise.all([
|
|
30310
|
+
(dependencies.smoke ?? smokeArtifactpassMcp)({
|
|
30311
|
+
mcpConfigPath: portable?.mcpConfig ?? "",
|
|
30312
|
+
localConfigPath: context.configPath
|
|
30313
|
+
}),
|
|
30314
|
+
verifySkills(portable)
|
|
30315
|
+
]);
|
|
30316
|
+
}
|
|
30317
|
+
});
|
|
30318
|
+
} else {
|
|
30319
|
+
const previousSettings = configSnapshot?.existed === true && configSnapshot.bytes !== void 0 ? await readLocalBridgeSettings(configPath) : null;
|
|
30320
|
+
const previousProfile = previousSettings?.profiles[profileName];
|
|
30321
|
+
if (previousProfile !== void 0 && new URL(previousProfile.base_url).origin !== new URL(origin).origin) {
|
|
30322
|
+
throw new Error(
|
|
30323
|
+
`ArtifactPass ${profileName} already targets ${new URL(previousProfile.base_url).origin}; use a new profile or disconnect it before changing deployments`
|
|
30324
|
+
);
|
|
30325
|
+
}
|
|
30326
|
+
const installedSettings = upsertLocalBridgeProfile(
|
|
30327
|
+
previousSettings,
|
|
30328
|
+
profileName,
|
|
30329
|
+
{
|
|
30330
|
+
base_url: origin,
|
|
30331
|
+
workspace_roots: [workspaceRoot],
|
|
30332
|
+
...input.openDevelopment === true ? { open_development: true } : {},
|
|
30333
|
+
...previousProfile?.pdf_key_id === void 0 ? {} : { pdf_key_id: previousProfile.pdf_key_id },
|
|
30334
|
+
...previousProfile?.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
30335
|
+
...previousProfile?.publication_state_path === void 0 ? {} : { publication_state_path: previousProfile.publication_state_path },
|
|
30336
|
+
credential_namespace: "artifactpass",
|
|
30337
|
+
...previousProfile?.credential_binding === "origin" ? { credential_binding: "origin" } : {}
|
|
30338
|
+
}
|
|
30339
|
+
);
|
|
30340
|
+
await writeLocalBridgeSettings(
|
|
30341
|
+
configPath,
|
|
30342
|
+
previousSettings !== null && input.profileName === void 0 && input.openDevelopment !== true ? setActiveLocalBridgeProfile(installedSettings, previousSettings.active_profile) : installedSettings
|
|
30343
|
+
);
|
|
30344
|
+
const runner = dependencies.runner ?? runProcess;
|
|
30345
|
+
const hosts = input.installKnownHostAdapters === false ? [] : await detectHosts(runner);
|
|
30346
|
+
hostInstallation = hosts.length === 0 ? void 0 : await installPluginForHosts(hosts, input.marketplaceSource, {
|
|
30347
|
+
configPath,
|
|
30348
|
+
profileName,
|
|
30349
|
+
bridgePath: resolve6(portable.rootDirectory, "plugin/dist/cli.mjs")
|
|
30350
|
+
}, runner);
|
|
30351
|
+
[smoke, skills] = await Promise.all([
|
|
30352
|
+
(dependencies.smoke ?? smokeArtifactpassMcp)({
|
|
30353
|
+
mcpConfigPath: portable.mcpConfig,
|
|
30354
|
+
localConfigPath: configPath
|
|
30355
|
+
}),
|
|
30356
|
+
verifySkills(portable)
|
|
30357
|
+
]);
|
|
30358
|
+
connectResult = {
|
|
30359
|
+
hosts,
|
|
30360
|
+
profileName,
|
|
30361
|
+
configPath
|
|
30362
|
+
};
|
|
30363
|
+
}
|
|
29973
30364
|
outcomes.push(`credential:${connectResult.credentialAction ?? "none"}`);
|
|
29974
30365
|
outcomes.push("host-registration:installed-or-reported");
|
|
29975
30366
|
await dependencies.afterStage?.("connection");
|
|
@@ -30027,6 +30418,11 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
30027
30418
|
return receipt;
|
|
30028
30419
|
} catch (error51) {
|
|
30029
30420
|
const rollbackFailures = [];
|
|
30421
|
+
if (hostInstallation !== void 0) {
|
|
30422
|
+
await hostInstallation.rollback().catch(() => rollbackFailures.push("host-registration"));
|
|
30423
|
+
} else if ((connectResult?.hosts.length ?? 0) > 0) {
|
|
30424
|
+
rollbackFailures.push("host-registration-unverified");
|
|
30425
|
+
}
|
|
30030
30426
|
if (portable !== void 0 && (dependencies.portableWasCreated ?? portableIntegrationWasCreated)(portable)) {
|
|
30031
30427
|
await rm5(portable.rootDirectory, { recursive: true, force: true }).catch(() => rollbackFailures.push("portable-bundle"));
|
|
30032
30428
|
}
|
|
@@ -30034,7 +30430,6 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
30034
30430
|
const restore = configSnapshot.existed && configSnapshot.bytes !== void 0 ? writeFile5(configPath, configSnapshot.bytes, { mode: 384 }) : rm5(configPath, { force: true });
|
|
30035
30431
|
await restore.catch(() => rollbackFailures.push("configuration"));
|
|
30036
30432
|
}
|
|
30037
|
-
if ((connectResult?.hosts.length ?? 0) > 0) rollbackFailures.push("host-registration-unverified");
|
|
30038
30433
|
if (connectResult?.credentialAction === "created" || connectResult?.credentialAction === "rotated") {
|
|
30039
30434
|
rollbackFailures.push("credential-unverified");
|
|
30040
30435
|
}
|
|
@@ -30117,11 +30512,6 @@ var booleanFlag = (args, flag) => {
|
|
|
30117
30512
|
return count === 1;
|
|
30118
30513
|
};
|
|
30119
30514
|
var positionalValues = (args) => args.filter((item, index) => index === 0 || !args[index - 1]?.startsWith("--")).filter((item) => !item.startsWith("--"));
|
|
30120
|
-
var positional = (args, position) => {
|
|
30121
|
-
const result = positionalValues(args)[position];
|
|
30122
|
-
if (result === void 0) throw new Error("A deployment URL is required");
|
|
30123
|
-
return result;
|
|
30124
|
-
};
|
|
30125
30515
|
var optionalPositional = (args, position) => positionalValues(args)[position];
|
|
30126
30516
|
var print = (valueToPrint) => {
|
|
30127
30517
|
process.stdout.write(`${typeof valueToPrint === "string" ? valueToPrint : JSON.stringify(valueToPrint, null, 2)}
|
|
@@ -30132,14 +30522,20 @@ var help = `ArtifactPass setup
|
|
|
30132
30522
|
Commands:
|
|
30133
30523
|
artifactpass [--json]
|
|
30134
30524
|
install [--base-url <url>] [--profile <name>] [--workspace-root <path>] [--open-development] [--no-host-install] [--json]
|
|
30525
|
+
deploy-public --account-id <id> --zone-id <id> --hostname <host> [--service-name <name>] --workers-subdomain <name> --pdf-key-id <id> --pdf-public-key <base64> --google-client-id <id> --github-client-id <id> (--dry-run | --write-approval-manifest <path> | --approve-manifest <path>)
|
|
30135
30526
|
deploy --account-id <id> --zone-id <id> --hostname <host> [--service-name <name>] --workers-subdomain <name> --pdf-key-id <id> --pdf-public-key <base64> (--allow-email <email> | --allow-domain <domain>) (--dry-run | --write-approval-manifest <path> | --approve-manifest <path>)
|
|
30136
|
-
connect
|
|
30527
|
+
connect [base-url] [--profile <name>] [--workspace-root <path>] [--host codex|claude|both] [--no-host-install] [--marketplace <source>] [--open-development]
|
|
30137
30528
|
profile list
|
|
30138
30529
|
profile use <name>
|
|
30139
30530
|
disconnect [--profile <name>]
|
|
30140
30531
|
doctor
|
|
30141
30532
|
|
|
30142
30533
|
Cloudflare credentials come from CLOUDFLARE_API_TOKEN or Wrangler OAuth and are never persisted by ArtifactPass.`;
|
|
30534
|
+
var requiredEnvironment = (name) => {
|
|
30535
|
+
const result = process.env[name];
|
|
30536
|
+
if (result === void 0 || result.length === 0) throw new Error(`${name} is required`);
|
|
30537
|
+
return result;
|
|
30538
|
+
};
|
|
30143
30539
|
var jsonOutputRequested = false;
|
|
30144
30540
|
var main = async () => {
|
|
30145
30541
|
const [command, ...args] = process.argv.slice(2);
|
|
@@ -30163,6 +30559,7 @@ var main = async () => {
|
|
|
30163
30559
|
...profileName === void 0 ? {} : { profileName },
|
|
30164
30560
|
...workspaceRoot === void 0 ? {} : { workspaceRoot },
|
|
30165
30561
|
openDevelopment,
|
|
30562
|
+
connectAfterInstall: false,
|
|
30166
30563
|
installKnownHostAdapters: !booleanFlag(installArgs, "--no-host-install")
|
|
30167
30564
|
}, {
|
|
30168
30565
|
connectDependencies: {
|
|
@@ -30189,6 +30586,39 @@ ${url2}
|
|
|
30189
30586
|
if (!result.node || !result.wrangler || !result.deploymentAssets) process.exitCode = 1;
|
|
30190
30587
|
return;
|
|
30191
30588
|
}
|
|
30589
|
+
if (command === "deploy-public") {
|
|
30590
|
+
const dryRun = booleanFlag(args, "--dry-run");
|
|
30591
|
+
const writeApprovalManifest = optionalValue(args, "--write-approval-manifest");
|
|
30592
|
+
const approveManifest = optionalValue(args, "--approve-manifest");
|
|
30593
|
+
if ([dryRun, writeApprovalManifest !== void 0, approveManifest !== void 0].filter(Boolean).length !== 1) {
|
|
30594
|
+
throw new Error("Choose exactly one of --dry-run, --write-approval-manifest, or --approve-manifest");
|
|
30595
|
+
}
|
|
30596
|
+
const serviceName = optionalValue(args, "--service-name");
|
|
30597
|
+
const result = await runDeployCommand({
|
|
30598
|
+
accountId: value(args, "--account-id"),
|
|
30599
|
+
zoneId: value(args, "--zone-id"),
|
|
30600
|
+
hostname: value(args, "--hostname"),
|
|
30601
|
+
pdfKeyId: value(args, "--pdf-key-id"),
|
|
30602
|
+
pdfPublicKey: value(args, "--pdf-public-key"),
|
|
30603
|
+
workersSubdomain: value(args, "--workers-subdomain"),
|
|
30604
|
+
identities: [],
|
|
30605
|
+
dryRun,
|
|
30606
|
+
publicAuth: {
|
|
30607
|
+
googleClientId: value(args, "--google-client-id"),
|
|
30608
|
+
googleClientSecret: requiredEnvironment("ARTIFACTPASS_GOOGLE_OAUTH_CLIENT_SECRET"),
|
|
30609
|
+
githubClientId: value(args, "--github-client-id"),
|
|
30610
|
+
githubClientSecret: requiredEnvironment("ARTIFACTPASS_GITHUB_OAUTH_CLIENT_SECRET")
|
|
30611
|
+
},
|
|
30612
|
+
...serviceName === void 0 ? {} : { serviceName },
|
|
30613
|
+
...writeApprovalManifest === void 0 ? {} : { writeApprovalManifest: resolve7(writeApprovalManifest) },
|
|
30614
|
+
...approveManifest === void 0 ? {} : { approveManifest: resolve7(approveManifest) }
|
|
30615
|
+
}, {
|
|
30616
|
+
deploymentRoot,
|
|
30617
|
+
...process.env.CLOUDFLARE_API_TOKEN === void 0 ? {} : { token: process.env.CLOUDFLARE_API_TOKEN }
|
|
30618
|
+
});
|
|
30619
|
+
print(result);
|
|
30620
|
+
return;
|
|
30621
|
+
}
|
|
30192
30622
|
if (command === "deploy") {
|
|
30193
30623
|
const dryRun = booleanFlag(args, "--dry-run");
|
|
30194
30624
|
const writeApprovalManifest = optionalValue(args, "--write-approval-manifest");
|
|
@@ -30221,6 +30651,12 @@ ${url2}
|
|
|
30221
30651
|
return;
|
|
30222
30652
|
}
|
|
30223
30653
|
if (command === "connect") {
|
|
30654
|
+
const connectArguments = parseConnectArguments(args);
|
|
30655
|
+
await migrateDefaultLocalState();
|
|
30656
|
+
const savedSettings = await readLocalBridgeSettings(defaultLocalConfigPath()).catch((error51) => {
|
|
30657
|
+
if (error51.code === "ENOENT") return null;
|
|
30658
|
+
throw error51;
|
|
30659
|
+
});
|
|
30224
30660
|
const installKnownHostAdapters = !booleanFlag(args, "--no-host-install");
|
|
30225
30661
|
const requestedHost = optionalValue(args, "--host");
|
|
30226
30662
|
const host = requestedHost ?? "both";
|
|
@@ -30230,17 +30666,18 @@ ${url2}
|
|
|
30230
30666
|
}
|
|
30231
30667
|
const hosts = host === "both" ? void 0 : [host];
|
|
30232
30668
|
const marketplaceSource = optionalValue(args, "--marketplace") ?? defaultMarketplace;
|
|
30233
|
-
const portableIntegration =
|
|
30669
|
+
const portableIntegration = await installPortableIntegration({
|
|
30234
30670
|
sourceRoot: resolve7(marketplaceSource, "plugins/artifactpass")
|
|
30235
30671
|
});
|
|
30236
30672
|
const profileName = optionalValue(args, "--profile");
|
|
30237
30673
|
const result = await connectHost({
|
|
30238
30674
|
...profileName === void 0 ? {} : { profileName },
|
|
30239
|
-
baseUrl:
|
|
30675
|
+
baseUrl: resolveConnectDeploymentUrl(connectArguments, savedSettings, profileName),
|
|
30240
30676
|
workspaceRoots: values(args, "--workspace-root").length > 0 ? values(args, "--workspace-root") : [process.cwd()],
|
|
30241
30677
|
...hosts === void 0 ? {} : { hosts },
|
|
30242
30678
|
installKnownHostAdapters,
|
|
30243
30679
|
marketplaceSource,
|
|
30680
|
+
...installKnownHostAdapters ? { hostBridgePath: resolve7(portableIntegration.rootDirectory, "plugin/dist/cli.mjs") } : {},
|
|
30244
30681
|
openDevelopment: booleanFlag(args, "--open-development")
|
|
30245
30682
|
}, {
|
|
30246
30683
|
deviceFlowDependencies: {
|