Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ jobs:
# Scheduled/manual runs retain the full OS × Node matrix for releases.
matrix: ${{ fromJSON(needs.plan.outputs.matrix) }}
runs-on: ${{ matrix.os }}
timeout-minutes: 10
# Windows bundle installs (real tar extraction + junction creation per initWith call) run several times
# slower than Linux/macOS; the last test alone does ~11 of them plus two CLI subprocess runs, which
# comfortably clears 10 minutes on Linux/macOS but not on windows-latest.
timeout-minutes: 20
env:
URLCODE_AUTH_STORE_STARTUP_MS: '60000'
steps:
Expand Down
2 changes: 2 additions & 0 deletions packages/admin/src/scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface ScaffoldRequest {
hostFile: string;
/** Every extension name being composed, in canonical order independent of the `--with` spelling. */
names: readonly string[];
/** `bundle`: core's --with always requests this. `npm`, from the operator's own install, is reachable only from
* each package's own standalone init CLI (urlcode-auth init, urlcode-admin init), not from --with. */
distribution?: 'npm' | 'bundle';
}
export interface ScaffoldFile {
Expand Down
2 changes: 2 additions & 0 deletions packages/auth/src/scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export interface ScaffoldRequest {
hostFile: string;
/** Every extension name being scaffolded together, including this one. */
names: readonly string[];
/** `bundle`: core's --with always requests this. `npm`, from the operator's own install, is reachable only from
* each package's own standalone init CLI (urlcode-auth init, urlcode-admin init), not from --with. */
distribution?: 'npm' | 'bundle';
}
export interface ScaffoldFile {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/extension-bundles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ async function writeLock(project:string,lock:BundleLock):Promise<void>{const pat
export const githubBundleTransport:BundleTransport=createGithubTransport({repository:BUNDLE_REPOSITORY,workflow:BUNDLE_WORKFLOW,tagPattern:tag,exampleTag:'extension-bundles@v1.0.0',maxAssetSize:limits.archive,itemLabel:'extension bundle'});
async function verified(assets:ReleaseAsset[],asset:string,release:string,transport:BundleTransport):Promise<Uint8Array>{return verifiedReleaseAsset(assets,asset,release,transport,'extension bundle','urlcode-bundle-attest');}
export async function installBundle(project:string,release:string,bundleName:string,transport:BundleTransport=githubBundleTransport):Promise<BundleLock>{assert(name.test(bundleName),'Invalid extension bundle name');const assets=await transport.release(release),catalog=parseBundleCatalog(await verified(assets,'extension-bundles-catalog.json',release,transport),release),item=catalog.bundles.find(value=>value.name===bundleName);assert(item,`Extension bundle ${bundleName} is not in the signed catalog`);const revoked=catalog.revoked.find(value=>value.sha256===item.sha256);assert(!revoked,`Extension bundle ${bundleName} is revoked: ${revoked?.reason??'unknown reason'}`);const locked:{catalog:{tag:string;commit:string};coreVersion:string}&BundleEntry={...item,catalog:{tag:catalog.tag,commit:catalog.commit},coreVersion:catalog.coreVersion};await extractBundle(await verified(assets,item.asset,release,transport),locked,bundleCachePath(project,item.sha256));let prior:BundleLock|undefined;try{prior=await readBundleLock(project);}catch{/* first install */}const bundles=(prior?.bundles??[]).filter(value=>value.name!==item.name);bundles.push(locked);bundles.sort((left,right)=>left.name.localeCompare(right.name));const lock={format:1 as const,bundles};await writeLock(project,lock);return lock;}
async function runningCoreVersion():Promise<string>{const raw:unknown=JSON.parse(await readFile(new URL('../../../package.json',import.meta.url),'utf8'));assert(record(raw)&&typeof raw.version==='string'&&version.test(raw.version),'Could not read the running core version');return raw.version;}
export async function runningCoreVersion():Promise<string>{const raw:unknown=JSON.parse(await readFile(new URL('../../../package.json',import.meta.url),'utf8'));assert(record(raw)&&typeof raw.version==='string'&&version.test(raw.version),'Could not read the running core version');return raw.version;}
/** Explicit host-only loader. It never reads project YAML, downloads, updates, or discovers code. */
export async function loadExtensionBundle(project:string,bundleName:string):Promise<Record<string,unknown>>{assert(name.test(bundleName),'Invalid extension bundle name');const lock=await readBundleLock(project),item=lock.bundles.find(value=>value.name===bundleName);assert(item,`Extension bundle ${bundleName} is not locked`);assert(item.coreVersion===await runningCoreVersion(),`Extension bundle ${bundleName} requires core ${item.coreVersion}; this runtime is incompatible`);const root=bundleCachePath(project,item.sha256);await validateCached(root,item);const module=await import(pathToFileURL(join(root,item.entry)).href);assert(module&&typeof module==='object',`Extension bundle ${bundleName} entry did not export a module`);return module as Record<string,unknown>;}
7 changes: 6 additions & 1 deletion packages/core/src/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,12 @@ export interface ScaffoldRequest {
hostFile:string;
/** Every extension name being scaffolded together, including this one, in a canonical (sorted) order that is independent of the `--with` spelling. */
names:readonly string[];
/** `npm` resolves extension packages from the operator's install; `bundle` resolves only already-verified, locked release bundles. */
/**
* `bundle` resolves only already-verified, locked release bundles; `urlcode init --with` always requests this and
* nothing else reaches it -- npm-package distribution is retired from that command. `npm`, imported from the
* operator's own install, remains reachable only from each package's own standalone quickstart CLI
* (`urlcode-auth init`, `urlcode-admin init`), a source-build tool distinct from --with.
*/
distribution?:'npm'|'bundle';
/**
* Operator acknowledgements from repeated `--ack <extension>:<id>` flags, sorted and de-duplicated; empty when none. Core treats
Expand Down
Loading
Loading