@volter/twin-catalog 0.2.3 → 0.2.5
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/catalog.json +1 -1
- package/docs/process.md +13 -0
- package/lib/browse.d.mts +13 -0
- package/lib/browse.mjs +21 -1
- package/package.json +2 -2
- package/policy.json +3 -3
- package/runner/prepare.mjs +10 -1
package/catalog.json
CHANGED
package/docs/process.md
CHANGED
|
@@ -42,6 +42,19 @@ recommendation is moderated separately from a submission and selects a package,
|
|
|
42
42
|
version is offered. Prereleases require an explicit version. A World pins package and version; a catalog update
|
|
43
43
|
does not change that pin. Removing a recommendation is not uninstalling a running World.
|
|
44
44
|
|
|
45
|
+
## Release information for users
|
|
46
|
+
|
|
47
|
+
Each assessed release exposes its artifact's description, license, Node requirements, kernel peer requirements,
|
|
48
|
+
source directory and issue tracker beside its integrity, provenance and measured behavior. README and license links
|
|
49
|
+
point to the source commit verified by npm provenance. They describe that version, not the publisher's current branch.
|
|
50
|
+
Historical assessments without these retained fields show them as unavailable; current registry metadata does not
|
|
51
|
+
fill missing historical evidence. A provenance link establishes source and build identity, not vendor fidelity.
|
|
52
|
+
|
|
53
|
+
Publishers describe useful workflows, setup and throwaway credential requirements, companion services, supported
|
|
54
|
+
SDK/API versions and explicit limitations in the package README. Model replies, simulated email/search and partial
|
|
55
|
+
interfaces are labeled. Declared gaps remain in the coverage denominator. No publisher badge or aggregate grade
|
|
56
|
+
substitutes for the exact release's supported operations, replay results and scope of browser measurements.
|
|
57
|
+
|
|
45
58
|
## Submission
|
|
46
59
|
|
|
47
60
|
A release PR adds exactly one `submissions/<id>.json`, with no executable files or index edits:
|
package/lib/browse.d.mts
CHANGED
|
@@ -45,6 +45,19 @@ export type Release = {
|
|
|
45
45
|
assessedAt?: string;
|
|
46
46
|
};
|
|
47
47
|
export type CatalogRelease = Release & {
|
|
48
|
+
packageMetadata: null | {
|
|
49
|
+
description: string | null;
|
|
50
|
+
license: string;
|
|
51
|
+
engines: Record<string, string>;
|
|
52
|
+
peerDependencies: Record<string, string>;
|
|
53
|
+
repositoryDirectory: string | null;
|
|
54
|
+
bugs: string | null;
|
|
55
|
+
sourceCommit: string | null;
|
|
56
|
+
readmeUrl: string | null;
|
|
57
|
+
licenseUrl: string | null;
|
|
58
|
+
packageUrl: string;
|
|
59
|
+
issuesUrl: string | null;
|
|
60
|
+
};
|
|
48
61
|
revoked: { reason: string } | null;
|
|
49
62
|
selectable: boolean;
|
|
50
63
|
default: boolean;
|
package/lib/browse.mjs
CHANGED
|
@@ -6,6 +6,25 @@ import { digest, loadIndex, read, requireThat, selection, stable, submissionId,
|
|
|
6
6
|
const textOrder = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
7
7
|
const releaseKey = (v) => `${v.package}@${v.version}`;
|
|
8
8
|
|
|
9
|
+
function packageDetails(bound, source, packageName, version) {
|
|
10
|
+
const metadata = bound?.report.prepared?.packageMetadata;
|
|
11
|
+
if (!metadata) return null;
|
|
12
|
+
const commit = bound.report.prepared?.provenance?.sourceCommit;
|
|
13
|
+
const directory = metadata.repositoryDirectory ?? '';
|
|
14
|
+
const parts = typeof directory === 'string' ? directory.split('/').filter(Boolean) : null;
|
|
15
|
+
const validDirectory = parts && parts.every((part) => part !== '.' && part !== '..' && !part.includes('\\'));
|
|
16
|
+
const sourceRoot = /^[a-f0-9]{40}$/.test(commit ?? '') && validDirectory
|
|
17
|
+
? `https://github.com/${source.repository}/blob/${commit}/${parts.length ? parts.map(encodeURIComponent).join('/') + '/' : ''}`
|
|
18
|
+
: null;
|
|
19
|
+
let issuesUrl = null;
|
|
20
|
+
try { const url = new URL(metadata.bugs); if (url.protocol === 'https:') issuesUrl = url.href; } catch { /* No usable issue URL was supplied. */ }
|
|
21
|
+
return { ...metadata, sourceCommit: commit ?? null,
|
|
22
|
+
readmeUrl: sourceRoot ? `${sourceRoot}README.md` : null,
|
|
23
|
+
licenseUrl: sourceRoot ? `${sourceRoot}LICENSE` : null,
|
|
24
|
+
packageUrl: `https://www.npmjs.com/package/${packageName}/v/${encodeURIComponent(version)}`,
|
|
25
|
+
issuesUrl };
|
|
26
|
+
}
|
|
27
|
+
|
|
9
28
|
function repositoryOf(pkg) {
|
|
10
29
|
const value = typeof pkg.repository === 'string' ? pkg.repository : pkg.repository?.url;
|
|
11
30
|
const match = /^git\+https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(value ?? '') ??
|
|
@@ -99,7 +118,8 @@ export function browse(root, { vendor, package: packageName, integrity = null }
|
|
|
99
118
|
const revoked = index.revocations.find((r) => r.package === p.name && r.version === v.version);
|
|
100
119
|
const selectable = v.status === 'live' && !v.version.includes('-') && !revoked;
|
|
101
120
|
const quick = bound?.report.quick, browser = bound?.report.browser;
|
|
102
|
-
return { ...v,
|
|
121
|
+
return { ...v, packageMetadata: packageDetails(bound, source, p.name, v.version),
|
|
122
|
+
revoked: revoked ? { reason: revoked.reason } : null, selectable: Boolean(selectable),
|
|
103
123
|
default: choice?.p.name === p.name && choice.v.version === v.version,
|
|
104
124
|
assessment: { recorded: record.assessed, available: Boolean(bound), evidence: record.evidence,
|
|
105
125
|
input: bound ? { repository: bound.envelope.input.repository, pullRequest: bound.envelope.input.pullRequest,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-catalog",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "The moderated twin distribution: approved versions and submission tooling for independent publishers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"evidence"
|
|
39
39
|
],
|
|
40
40
|
"catalog": {
|
|
41
|
-
"sourceCommit": "
|
|
41
|
+
"sourceCommit": "bd2fbbb3f0b46f8b8706e94b472673ce8e9b1033",
|
|
42
42
|
"digest": "1c9e35135ce16a67c8c5ba817277ac2e11869b8a1234206aee5674eb8851a134"
|
|
43
43
|
}
|
|
44
44
|
}
|
package/policy.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"registry": "https://registry.npmjs.org",
|
|
4
4
|
"tools": {
|
|
5
|
-
"@volter/world-core": "3.0.
|
|
6
|
-
"@volter/world-runtime": "3.0.
|
|
7
|
-
"@volter/twin-standard": "1.0.
|
|
5
|
+
"@volter/world-core": "3.0.69",
|
|
6
|
+
"@volter/world-runtime": "3.0.69",
|
|
7
|
+
"@volter/twin-standard": "1.0.61",
|
|
8
8
|
"playwright": "1.63.0"
|
|
9
9
|
},
|
|
10
10
|
"bun": "1.3.11",
|
package/runner/prepare.mjs
CHANGED
|
@@ -77,5 +77,14 @@ const provenance = await verifiedProvenance(await response.json(), source, bytes
|
|
|
77
77
|
// Keep a vendor-named package directory for the standard's public directory API; preserve the installed artifact.
|
|
78
78
|
mkdirSync('/work/packs', { recursive: true });
|
|
79
79
|
cpSync(join('/work/node_modules', s.package), join('/work/packs', s.vendor), { recursive: true });
|
|
80
|
-
|
|
80
|
+
// Retain listing facts from these exact bytes, never the registry's moving latest metadata.
|
|
81
|
+
const packageMetadata = {
|
|
82
|
+
description: typeof pack.description === 'string' ? pack.description : null,
|
|
83
|
+
license: pack.license,
|
|
84
|
+
engines: pack.engines ?? {},
|
|
85
|
+
peerDependencies: pack.peerDependencies ?? {},
|
|
86
|
+
repositoryDirectory: typeof pack.repository === 'object' ? pack.repository.directory ?? null : null,
|
|
87
|
+
bugs: typeof pack.bugs === 'string' ? pack.bugs : pack.bugs?.url ?? null,
|
|
88
|
+
};
|
|
89
|
+
write('/work/prepared.json', { schemaVersion: 1, submission: s, integrity: s.integrity, provenance, packageMetadata, dependencyLockSha256: digest(readFileSync('/work/package-lock.json', 'utf8')), clientSdkLocks, tools: policy.tools });
|
|
81
90
|
write('/work/world.json', { id: 'catalog-assessment', network: { egress: [] }, services: [] });
|