@kungfu-tech/buildchain 2.14.18-alpha.1 → 2.14.18-alpha.10
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/README.md +1 -0
- package/actions/promote-buildchain-ref/README.md +33 -30
- package/bin/buildchain.mjs +16 -4
- package/dist/site/buildchain-contract.json +86 -31
- package/dist/site/buildchain-site.json +88 -27
- package/dist/site/capability-registry.json +6 -5
- package/dist/site/cli-registry.json +12 -0
- package/dist/site/controller-registry.json +50 -6
- package/dist/site/kfd-claims.json +110 -21
- package/dist/site/kfd-upstream-aggregate.json +1 -1
- package/dist/site/manual-registry.json +21 -6
- package/dist/site/node-api-registry.json +19 -6
- package/dist/site/page-registry.json +70 -17
- package/dist/site/public-surface-audit.json +130 -23
- package/dist/site/publication-authority-registry.json +21 -1
- package/dist/site/publication-registry.json +4 -4
- package/dist/site/release-provenance.json +1 -0
- package/dist/site/site-manifest.json +18 -10
- package/dist/site/workflow-registry.json +62 -16
- package/docs/MAP.md +3 -1
- package/docs/github-governance-authority.md +267 -0
- package/docs/lifecycle-protocol.md +10 -10
- package/docs/publish-transaction.md +73 -4
- package/docs/release-governance.md +38 -24
- package/docs/reusable-build-surface.md +29 -11
- package/docs/web-surface-deployments.md +46 -0
- package/package.json +2 -1
- package/packages/core/buildchain-kfd-claims.js +2 -0
- package/packages/core/buildchain-publication-authority.js +1 -0
- package/packages/core/controller-evidence.js +1 -1
- package/packages/core/github-governance-authority.js +1312 -0
- package/packages/core/index.js +22 -0
- package/packages/core/publication-control-plane-audit.js +4 -1
- package/scripts/audit-github-governance.mjs +474 -0
- package/scripts/audit-publication-control-plane.mjs +41 -5
- package/scripts/check-inventory.mjs +8 -0
- package/scripts/generate-channel-promotion-workflow.mjs +3 -0
- package/scripts/generate-site-bundle.mjs +5 -0
- package/scripts/installer-publication.mjs +351 -0
- package/scripts/publication-commit-evidence.mjs +158 -0
- package/scripts/reconcile-github-governance.mjs +549 -0
- package/scripts/release-candidate-resolver.mjs +53 -0
- package/scripts/web-surface-core.mjs +127 -14
|
@@ -8,6 +8,7 @@ import { setTimeout as sleep } from "node:timers/promises";
|
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
import { loadBuildchainConfig, validateBuildchainConfig } from "../packages/core/buildchain-config.js";
|
|
10
10
|
import { createSurfaceTimestampPolicy } from "../packages/core/surface-manifest.js";
|
|
11
|
+
import { validateInstallerPublication, verifyInstallerPublicReadback } from "./installer-publication.mjs";
|
|
11
12
|
|
|
12
13
|
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
13
14
|
|
|
@@ -1004,6 +1005,18 @@ export function createWebSurfaceArtifactHash({ cwd = process.cwd(), artifactPath
|
|
|
1004
1005
|
};
|
|
1005
1006
|
}
|
|
1006
1007
|
|
|
1008
|
+
function installerPublicationEvidence(artifactRoot) {
|
|
1009
|
+
const manifestPath = path.join(artifactRoot, "installer-publication.json");
|
|
1010
|
+
if (!fs.existsSync(manifestPath)) return null;
|
|
1011
|
+
let publication;
|
|
1012
|
+
try {
|
|
1013
|
+
publication = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
1014
|
+
} catch (error) {
|
|
1015
|
+
throw new Error(`invalid installer publication manifest: ${error.message}`);
|
|
1016
|
+
}
|
|
1017
|
+
return validateInstallerPublication({ publication, artifactRoot });
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1007
1020
|
export function createWebSurfaceDeploymentManifest({
|
|
1008
1021
|
cwd = process.cwd(),
|
|
1009
1022
|
channel = "preview",
|
|
@@ -1133,6 +1146,12 @@ export function planWebSurfaceDeploy({
|
|
|
1133
1146
|
rollbackLimitations,
|
|
1134
1147
|
deployedAt,
|
|
1135
1148
|
});
|
|
1149
|
+
const installerEvidence = installerPublicationEvidence(
|
|
1150
|
+
path.resolve(cwd, artifactPath || deployConfig.artifactPath || "."),
|
|
1151
|
+
);
|
|
1152
|
+
if (installerEvidence) {
|
|
1153
|
+
manifest.installerPublicationEvidence = installerEvidence;
|
|
1154
|
+
}
|
|
1136
1155
|
const surfaceBindings = withImmutablePublicationPolicies(withSurfaceRoutingEvidence(manifest.surfaceBindings, {
|
|
1137
1156
|
artifactPath: artifactPath || deployConfig.artifactPath || ".",
|
|
1138
1157
|
files: resolvedArtifact.files,
|
|
@@ -1140,6 +1159,15 @@ export function planWebSurfaceDeploy({
|
|
|
1140
1159
|
cwd,
|
|
1141
1160
|
artifactPath: artifactPath || deployConfig.artifactPath || ".",
|
|
1142
1161
|
});
|
|
1162
|
+
if (installerEvidence) {
|
|
1163
|
+
const preserved = surfaceBindings.some((binding) =>
|
|
1164
|
+
binding.immutablePublication?.declaredPrefixes?.includes(installerEvidence.immutablePath));
|
|
1165
|
+
if (!preserved) {
|
|
1166
|
+
throw new Error(
|
|
1167
|
+
`installer immutable path is not covered by append-only publication policy: ${installerEvidence.immutablePath}`,
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1143
1171
|
manifest.surfaceBindings = surfaceBindings;
|
|
1144
1172
|
return {
|
|
1145
1173
|
schemaVersion: 1,
|
|
@@ -1953,6 +1981,42 @@ export async function checkWebSurfaceHealth({
|
|
|
1953
1981
|
});
|
|
1954
1982
|
}
|
|
1955
1983
|
|
|
1984
|
+
const installerPublication = manifest?.installerPublicationEvidence;
|
|
1985
|
+
const managedInstallerSurface =
|
|
1986
|
+
config.channels?.[channel]?.accessControl === "managed-network" &&
|
|
1987
|
+
!allowedManagedNetworkRunner;
|
|
1988
|
+
if (installerPublication && !managedInstallerSurface) {
|
|
1989
|
+
try {
|
|
1990
|
+
const publicBase = new URL(urls.hub || manifest?.url || Object.values(urls)[0]);
|
|
1991
|
+
const projected = {
|
|
1992
|
+
...installerPublication,
|
|
1993
|
+
assets: installerPublication.assets.map((asset) => ({
|
|
1994
|
+
...asset,
|
|
1995
|
+
friendlyUrl: new URL(new URL(asset.friendlyUrl).pathname, publicBase).href,
|
|
1996
|
+
immutableUrl: new URL(new URL(asset.immutableUrl).pathname, publicBase).href,
|
|
1997
|
+
})),
|
|
1998
|
+
};
|
|
1999
|
+
const evidence = await verifyInstallerPublicReadback({
|
|
2000
|
+
publication: projected,
|
|
2001
|
+
fetchImpl,
|
|
2002
|
+
});
|
|
2003
|
+
checks.push({
|
|
2004
|
+
surface: "__installer__",
|
|
2005
|
+
url: publicBase.href,
|
|
2006
|
+
status: "pass",
|
|
2007
|
+
evidence,
|
|
2008
|
+
message: "friendly and immutable installer routes match signed publication bytes and cache policy",
|
|
2009
|
+
});
|
|
2010
|
+
} catch (error) {
|
|
2011
|
+
checks.push({
|
|
2012
|
+
surface: "__installer__",
|
|
2013
|
+
url: urls.hub || manifest?.url || "",
|
|
2014
|
+
status: "fail",
|
|
2015
|
+
message: String(error.message || error),
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
|
|
1956
2020
|
const manifestChecks = bindings.map((binding) => ({
|
|
1957
2021
|
surface: binding.surface,
|
|
1958
2022
|
manifestKey: binding.manifestKey,
|
|
@@ -1987,6 +2051,20 @@ function deployBindingOperations({ artifactRoot, deployConfig, manifest, binding
|
|
|
1987
2051
|
const distribution = binding.distributionId || effectiveDeploy.cloudfront_distribution || effectiveDeploy.distribution || "";
|
|
1988
2052
|
const surfaceArtifactRoot = surfaceArtifactRootFor({ artifactRoot, binding });
|
|
1989
2053
|
const immutable = binding.immutablePublication;
|
|
2054
|
+
const installer = manifest.installerPublicationEvidence;
|
|
2055
|
+
const installerRoot = installer?.immutablePath || "";
|
|
2056
|
+
const ownsArtifactRoot = normalizeS3Key(
|
|
2057
|
+
binding.artifactPathPrefix || surfaceArtifactPrefix(binding),
|
|
2058
|
+
) === "";
|
|
2059
|
+
const ownsInstallerAssets = installer?.assets?.every((asset) =>
|
|
2060
|
+
fs.existsSync(path.join(surfaceArtifactRoot, asset.friendly.path)));
|
|
2061
|
+
const installerBinding =
|
|
2062
|
+
installer &&
|
|
2063
|
+
ownsArtifactRoot &&
|
|
2064
|
+
ownsInstallerAssets &&
|
|
2065
|
+
immutable?.declaredPrefixes?.includes(installer.immutablePath)
|
|
2066
|
+
? installer
|
|
2067
|
+
: null;
|
|
1990
2068
|
const immutableVerifier = path.join(moduleDir, "web-surface-immutable-object.mjs");
|
|
1991
2069
|
const verifyImmutable = (phase) => (immutable?.files || []).map((file) => ({
|
|
1992
2070
|
action: `verify-immutable-artifact-${phase}`,
|
|
@@ -2007,25 +2085,59 @@ function deployBindingOperations({ artifactRoot, deployConfig, manifest, binding
|
|
|
2007
2085
|
sha256: file.sha256,
|
|
2008
2086
|
},
|
|
2009
2087
|
}));
|
|
2010
|
-
const syncImmutable = (immutable?.preservedRoots || []).map((root) =>
|
|
2011
|
-
|
|
2088
|
+
const syncImmutable = (immutable?.preservedRoots || []).map((root) => {
|
|
2089
|
+
const isInstallerRoot = Boolean(installerBinding && root === installerRoot);
|
|
2090
|
+
const immutableMetadataArgs = isInstallerRoot
|
|
2091
|
+
? [
|
|
2092
|
+
"--content-type",
|
|
2093
|
+
"application/octet-stream",
|
|
2094
|
+
"--cache-control",
|
|
2095
|
+
"public,max-age=31536000,immutable",
|
|
2096
|
+
]
|
|
2097
|
+
: binding.cacheControl?.immutable
|
|
2098
|
+
? ["--cache-control", binding.cacheControl.immutable]
|
|
2099
|
+
: [];
|
|
2100
|
+
return {
|
|
2101
|
+
action: "sync-immutable-artifact",
|
|
2102
|
+
surface: binding.surface,
|
|
2103
|
+
command: "aws",
|
|
2104
|
+
args: [
|
|
2105
|
+
"s3",
|
|
2106
|
+
"sync",
|
|
2107
|
+
path.join(surfaceArtifactRoot, root),
|
|
2108
|
+
s3Uri(bucket, joinS3Key(binding.objectPrefix, root)),
|
|
2109
|
+
"--no-overwrite",
|
|
2110
|
+
"--checksum-algorithm",
|
|
2111
|
+
"SHA256",
|
|
2112
|
+
...immutableMetadataArgs,
|
|
2113
|
+
],
|
|
2114
|
+
immutable: {
|
|
2115
|
+
preservedRoot: root,
|
|
2116
|
+
overwrite: false,
|
|
2117
|
+
cacheControl: isInstallerRoot
|
|
2118
|
+
? "public,max-age=31536000,immutable"
|
|
2119
|
+
: binding.cacheControl?.immutable,
|
|
2120
|
+
},
|
|
2121
|
+
};
|
|
2122
|
+
});
|
|
2123
|
+
const publishFriendlyInstallers = (installerBinding?.assets || []).map((asset) => ({
|
|
2124
|
+
action: "publish-friendly-installer",
|
|
2012
2125
|
surface: binding.surface,
|
|
2013
2126
|
command: "aws",
|
|
2014
2127
|
args: [
|
|
2015
2128
|
"s3",
|
|
2016
|
-
"
|
|
2017
|
-
path.join(surfaceArtifactRoot,
|
|
2018
|
-
s3Uri(bucket, joinS3Key(binding.objectPrefix,
|
|
2019
|
-
"--
|
|
2020
|
-
|
|
2021
|
-
"
|
|
2022
|
-
|
|
2023
|
-
? ["--cache-control", binding.cacheControl.immutable]
|
|
2024
|
-
: []),
|
|
2129
|
+
"cp",
|
|
2130
|
+
path.join(surfaceArtifactRoot, asset.friendly.path),
|
|
2131
|
+
s3Uri(bucket, joinS3Key(binding.objectPrefix, asset.friendly.path)),
|
|
2132
|
+
"--content-type",
|
|
2133
|
+
asset.contentType,
|
|
2134
|
+
"--cache-control",
|
|
2135
|
+
"public,max-age=300,must-revalidate",
|
|
2025
2136
|
],
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2137
|
+
installer: {
|
|
2138
|
+
name: asset.name,
|
|
2139
|
+
digest: asset.digest,
|
|
2140
|
+
cacheControl: "public,max-age=300,must-revalidate",
|
|
2029
2141
|
},
|
|
2030
2142
|
}));
|
|
2031
2143
|
const operations = [
|
|
@@ -2068,6 +2180,7 @@ function deployBindingOperations({ artifactRoot, deployConfig, manifest, binding
|
|
|
2068
2180
|
excludes: binding.mutableDeleteExcludes || [],
|
|
2069
2181
|
}]
|
|
2070
2182
|
: []),
|
|
2183
|
+
...publishFriendlyInstallers,
|
|
2071
2184
|
...directoryIndexAliasOperations({ surfaceArtifactRoot, bucket, binding }),
|
|
2072
2185
|
{
|
|
2073
2186
|
action: "write-deployment-manifest",
|