artifactpass 0.1.0-rc.3 → 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 +485 -95
- package/dist/deployment/index.js +625 -50
- package/dist/deployment/migrations/0007-public-auth.sql +26 -0
- package/dist/deployment/wrangler-template.json +13 -2
- 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 +1 -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,
|
|
@@ -29573,15 +29812,26 @@ var connectHost = async (input, dependencies) => {
|
|
|
29573
29812
|
...migration === void 0 ? {} : { migration }
|
|
29574
29813
|
};
|
|
29575
29814
|
}
|
|
29576
|
-
const
|
|
29577
|
-
if (
|
|
29815
|
+
const previousStoredCredential = await store.get();
|
|
29816
|
+
if (previousStoredCredential !== null && previousProfile === void 0) {
|
|
29578
29817
|
throw new Error(`The existing ArtifactPass ${profileName} credential has no matching profile; disconnect it first`);
|
|
29579
29818
|
}
|
|
29580
|
-
|
|
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) {
|
|
29581
29825
|
const inspection = await inspectToken(origin, previousToken, fetchImplementation);
|
|
29582
29826
|
if (inspection !== null) {
|
|
29583
29827
|
if (previousSettings === null) throw new Error("ArtifactPass profile state disappeared");
|
|
29828
|
+
const boundCredential = bindAgentCredential(origin, previousToken);
|
|
29829
|
+
let migratedCredential = false;
|
|
29584
29830
|
try {
|
|
29831
|
+
if (boundCredential !== previousStoredCredential) {
|
|
29832
|
+
await store.set(boundCredential);
|
|
29833
|
+
migratedCredential = true;
|
|
29834
|
+
}
|
|
29585
29835
|
await (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, upsertLocalBridgeProfile(
|
|
29586
29836
|
previousSettings,
|
|
29587
29837
|
profileName,
|
|
@@ -29591,11 +29841,13 @@ var connectHost = async (input, dependencies) => {
|
|
|
29591
29841
|
...previousProfile.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
29592
29842
|
...previousProfile.publication_state_path === void 0 ? {} : { publication_state_path: previousProfile.publication_state_path },
|
|
29593
29843
|
credential_namespace: "artifactpass",
|
|
29844
|
+
credential_binding: "origin",
|
|
29594
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 }
|
|
29595
29846
|
}
|
|
29596
29847
|
));
|
|
29597
29848
|
await installAndVerify();
|
|
29598
29849
|
} catch (error51) {
|
|
29850
|
+
if (migratedCredential) await store.set(previousStoredCredential);
|
|
29599
29851
|
await (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, previousSettings).catch((rollbackError) => {
|
|
29600
29852
|
throw new AggregateError([error51, rollbackError], "ArtifactPass connection verification failed and config rollback was incomplete");
|
|
29601
29853
|
});
|
|
@@ -29628,11 +29880,12 @@ var connectHost = async (input, dependencies) => {
|
|
|
29628
29880
|
...previousProfile?.publication_state === "legacy" ? { publication_state: "legacy" } : {},
|
|
29629
29881
|
...previousProfile?.publication_state_path === void 0 ? {} : { publication_state_path: previousProfile.publication_state_path },
|
|
29630
29882
|
credential_namespace: "artifactpass",
|
|
29883
|
+
credential_binding: "origin",
|
|
29631
29884
|
...healthBody.pdf_provenance_key_id === void 0 ? {} : { pdf_key_id: healthBody.pdf_provenance_key_id }
|
|
29632
29885
|
}
|
|
29633
29886
|
));
|
|
29634
29887
|
wroteConfig = true;
|
|
29635
|
-
await store.set(token.accessToken);
|
|
29888
|
+
await store.set(bindAgentCredential(origin, token.accessToken));
|
|
29636
29889
|
rollbackHostInstallation = await installAndVerify();
|
|
29637
29890
|
if (previousToken !== null && previousProfile !== void 0 && previousProfile.open_development !== true) {
|
|
29638
29891
|
await revokeToken(
|
|
@@ -29649,10 +29902,10 @@ var connectHost = async (input, dependencies) => {
|
|
|
29649
29902
|
await revokeToken(origin, token.accessToken, fetchImplementation).catch((cleanupError) => {
|
|
29650
29903
|
cleanupErrors.push(cleanupError);
|
|
29651
29904
|
});
|
|
29652
|
-
if (
|
|
29905
|
+
if (previousStoredCredential === null) {
|
|
29653
29906
|
await store.delete().catch((cleanupError) => cleanupErrors.push(cleanupError));
|
|
29654
29907
|
} else {
|
|
29655
|
-
await store.set(
|
|
29908
|
+
await store.set(previousStoredCredential).catch((cleanupError) => cleanupErrors.push(cleanupError));
|
|
29656
29909
|
}
|
|
29657
29910
|
if (wroteConfig) {
|
|
29658
29911
|
const restoreConfig = previousSettings === null ? rm4(configPath, { force: true }) : (dependencies.writeSettings ?? writeLocalBridgeSettings)(configPath, previousSettings);
|
|
@@ -29668,7 +29921,7 @@ var connectHost = async (input, dependencies) => {
|
|
|
29668
29921
|
profileName,
|
|
29669
29922
|
expiresIn: token.expiresIn,
|
|
29670
29923
|
configPath,
|
|
29671
|
-
credentialAction:
|
|
29924
|
+
credentialAction: previousStoredCredential === null ? "created" : "rotated",
|
|
29672
29925
|
...portableIntegration === void 0 ? {} : { portableIntegration },
|
|
29673
29926
|
...migration === void 0 ? {} : { migration }
|
|
29674
29927
|
};
|
|
@@ -29704,9 +29957,10 @@ var disconnectHost = async (baseUrl, options = {}) => {
|
|
|
29704
29957
|
}),
|
|
29705
29958
|
migrationCommitted: true
|
|
29706
29959
|
});
|
|
29707
|
-
const
|
|
29708
|
-
if (
|
|
29960
|
+
const storedCredential = await store.get();
|
|
29961
|
+
if (storedCredential === null) return;
|
|
29709
29962
|
const origin = assertSafeDeploymentOrigin(new URL(baseUrl));
|
|
29963
|
+
const token = resolveAgentCredential(storedCredential, origin);
|
|
29710
29964
|
const response = await (options.fetch ?? globalThis.fetch)(new URL("/api/connection", origin), {
|
|
29711
29965
|
method: "DELETE",
|
|
29712
29966
|
headers: { Authorization: `Bearer ${token}` },
|
|
@@ -29718,6 +29972,45 @@ var disconnectHost = async (baseUrl, options = {}) => {
|
|
|
29718
29972
|
await store.delete();
|
|
29719
29973
|
};
|
|
29720
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
|
+
|
|
29721
30014
|
// src/doctor.ts
|
|
29722
30015
|
import { access, constants } from "node:fs/promises";
|
|
29723
30016
|
var commandExists = async (runner, command) => {
|
|
@@ -29767,7 +30060,7 @@ import { dirname as dirname6, join as join2, parse as parse3, resolve as resolve
|
|
|
29767
30060
|
// package.json
|
|
29768
30061
|
var package_default = {
|
|
29769
30062
|
name: "artifactpass",
|
|
29770
|
-
version: "0.1.0-rc.
|
|
30063
|
+
version: "0.1.0-rc.4",
|
|
29771
30064
|
description: "Install and connect ArtifactPass for compatible AI agent systems.",
|
|
29772
30065
|
repository: {
|
|
29773
30066
|
type: "git",
|
|
@@ -29935,9 +30228,11 @@ var renderInstallReceipt = (receipt) => {
|
|
|
29935
30228
|
return `ArtifactPass installation failed during ${receipt.failed_stage ?? "setup"}. Previous working state was restored.`;
|
|
29936
30229
|
}
|
|
29937
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 ")}.`;
|
|
29938
|
-
|
|
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.`;
|
|
29939
30233
|
};
|
|
29940
30234
|
var runArtifactpassInstall = async (input, dependencies) => {
|
|
30235
|
+
const connectAfterInstall = input.connectAfterInstall === true;
|
|
29941
30236
|
const now = dependencies.now ?? Date.now;
|
|
29942
30237
|
const operationId = (dependencies.operationId ?? randomUUID3)();
|
|
29943
30238
|
const origin = new URL(input.baseUrl ?? "https://artifactpass.com").origin;
|
|
@@ -29958,6 +30253,7 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29958
30253
|
let smoke;
|
|
29959
30254
|
let skills = [];
|
|
29960
30255
|
let connectResult;
|
|
30256
|
+
let hostInstallation;
|
|
29961
30257
|
let configSnapshot;
|
|
29962
30258
|
const outcomes = [];
|
|
29963
30259
|
try {
|
|
@@ -29977,7 +30273,7 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29977
30273
|
if (isMissing(error51)) return { existed: false };
|
|
29978
30274
|
throw error51;
|
|
29979
30275
|
});
|
|
29980
|
-
if (dependencies.skipCredentialStorePreflight !== true && input.openDevelopment !== true) {
|
|
30276
|
+
if (connectAfterInstall && dependencies.skipCredentialStorePreflight !== true && input.openDevelopment !== true) {
|
|
29981
30277
|
await verifyCredentialStore(
|
|
29982
30278
|
dependencies.platform ?? process.platform,
|
|
29983
30279
|
dependencies.runner ?? runProcess
|
|
@@ -29997,25 +30293,74 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
29997
30293
|
stage = "connection";
|
|
29998
30294
|
journal = { ...journal, stage };
|
|
29999
30295
|
await writeJson(journalPath, journal);
|
|
30000
|
-
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
|
|
30005
|
-
|
|
30006
|
-
|
|
30007
|
-
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
|
|
30011
|
-
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
|
|
30017
|
-
|
|
30018
|
-
|
|
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
|
+
}
|
|
30019
30364
|
outcomes.push(`credential:${connectResult.credentialAction ?? "none"}`);
|
|
30020
30365
|
outcomes.push("host-registration:installed-or-reported");
|
|
30021
30366
|
await dependencies.afterStage?.("connection");
|
|
@@ -30073,6 +30418,11 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
30073
30418
|
return receipt;
|
|
30074
30419
|
} catch (error51) {
|
|
30075
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
|
+
}
|
|
30076
30426
|
if (portable !== void 0 && (dependencies.portableWasCreated ?? portableIntegrationWasCreated)(portable)) {
|
|
30077
30427
|
await rm5(portable.rootDirectory, { recursive: true, force: true }).catch(() => rollbackFailures.push("portable-bundle"));
|
|
30078
30428
|
}
|
|
@@ -30080,7 +30430,6 @@ var runArtifactpassInstall = async (input, dependencies) => {
|
|
|
30080
30430
|
const restore = configSnapshot.existed && configSnapshot.bytes !== void 0 ? writeFile5(configPath, configSnapshot.bytes, { mode: 384 }) : rm5(configPath, { force: true });
|
|
30081
30431
|
await restore.catch(() => rollbackFailures.push("configuration"));
|
|
30082
30432
|
}
|
|
30083
|
-
if ((connectResult?.hosts.length ?? 0) > 0) rollbackFailures.push("host-registration-unverified");
|
|
30084
30433
|
if (connectResult?.credentialAction === "created" || connectResult?.credentialAction === "rotated") {
|
|
30085
30434
|
rollbackFailures.push("credential-unverified");
|
|
30086
30435
|
}
|
|
@@ -30163,11 +30512,6 @@ var booleanFlag = (args, flag) => {
|
|
|
30163
30512
|
return count === 1;
|
|
30164
30513
|
};
|
|
30165
30514
|
var positionalValues = (args) => args.filter((item, index) => index === 0 || !args[index - 1]?.startsWith("--")).filter((item) => !item.startsWith("--"));
|
|
30166
|
-
var positional = (args, position) => {
|
|
30167
|
-
const result = positionalValues(args)[position];
|
|
30168
|
-
if (result === void 0) throw new Error("A deployment URL is required");
|
|
30169
|
-
return result;
|
|
30170
|
-
};
|
|
30171
30515
|
var optionalPositional = (args, position) => positionalValues(args)[position];
|
|
30172
30516
|
var print = (valueToPrint) => {
|
|
30173
30517
|
process.stdout.write(`${typeof valueToPrint === "string" ? valueToPrint : JSON.stringify(valueToPrint, null, 2)}
|
|
@@ -30178,14 +30522,20 @@ var help = `ArtifactPass setup
|
|
|
30178
30522
|
Commands:
|
|
30179
30523
|
artifactpass [--json]
|
|
30180
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>)
|
|
30181
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>)
|
|
30182
|
-
connect
|
|
30527
|
+
connect [base-url] [--profile <name>] [--workspace-root <path>] [--host codex|claude|both] [--no-host-install] [--marketplace <source>] [--open-development]
|
|
30183
30528
|
profile list
|
|
30184
30529
|
profile use <name>
|
|
30185
30530
|
disconnect [--profile <name>]
|
|
30186
30531
|
doctor
|
|
30187
30532
|
|
|
30188
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
|
+
};
|
|
30189
30539
|
var jsonOutputRequested = false;
|
|
30190
30540
|
var main = async () => {
|
|
30191
30541
|
const [command, ...args] = process.argv.slice(2);
|
|
@@ -30209,6 +30559,7 @@ var main = async () => {
|
|
|
30209
30559
|
...profileName === void 0 ? {} : { profileName },
|
|
30210
30560
|
...workspaceRoot === void 0 ? {} : { workspaceRoot },
|
|
30211
30561
|
openDevelopment,
|
|
30562
|
+
connectAfterInstall: false,
|
|
30212
30563
|
installKnownHostAdapters: !booleanFlag(installArgs, "--no-host-install")
|
|
30213
30564
|
}, {
|
|
30214
30565
|
connectDependencies: {
|
|
@@ -30235,6 +30586,39 @@ ${url2}
|
|
|
30235
30586
|
if (!result.node || !result.wrangler || !result.deploymentAssets) process.exitCode = 1;
|
|
30236
30587
|
return;
|
|
30237
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
|
+
}
|
|
30238
30622
|
if (command === "deploy") {
|
|
30239
30623
|
const dryRun = booleanFlag(args, "--dry-run");
|
|
30240
30624
|
const writeApprovalManifest = optionalValue(args, "--write-approval-manifest");
|
|
@@ -30267,6 +30651,12 @@ ${url2}
|
|
|
30267
30651
|
return;
|
|
30268
30652
|
}
|
|
30269
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
|
+
});
|
|
30270
30660
|
const installKnownHostAdapters = !booleanFlag(args, "--no-host-install");
|
|
30271
30661
|
const requestedHost = optionalValue(args, "--host");
|
|
30272
30662
|
const host = requestedHost ?? "both";
|
|
@@ -30282,7 +30672,7 @@ ${url2}
|
|
|
30282
30672
|
const profileName = optionalValue(args, "--profile");
|
|
30283
30673
|
const result = await connectHost({
|
|
30284
30674
|
...profileName === void 0 ? {} : { profileName },
|
|
30285
|
-
baseUrl:
|
|
30675
|
+
baseUrl: resolveConnectDeploymentUrl(connectArguments, savedSettings, profileName),
|
|
30286
30676
|
workspaceRoots: values(args, "--workspace-root").length > 0 ? values(args, "--workspace-root") : [process.cwd()],
|
|
30287
30677
|
...hosts === void 0 ? {} : { hosts },
|
|
30288
30678
|
installKnownHostAdapters,
|