@extenshi/cli 0.0.8 → 0.0.9

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.
@@ -0,0 +1,43 @@
1
+ /**
2
+ * review-risk — fetch the last-published manifest for an extension from the
3
+ * Extenshi catalog so check 3 can diff against it. This is the part that is
4
+ * unique to us: we keep per-extension manifest snapshots, so we can tell you
5
+ * whether *this* update adds an auto-disabling permission versus what's live.
6
+ *
7
+ * Talks to the public BFF tRPC gateway:
8
+ * GET {bffUrl}/api/trpc/store.getLatestPublishedManifest?input=<json>
9
+ *
10
+ * The BFF read path may be gated behind a developer API key, so we send the
11
+ * `ek_` key when the caller has one. Everything here is fail-soft: any problem
12
+ * (key required, extension unknown, catalog older than this CLI, network error)
13
+ * resolves to `{ manifest: null, reason }` — the command then runs every other
14
+ * check and prints why the diff was skipped, rather than failing the run.
15
+ */
16
+ export interface PriorManifestResult {
17
+ /** The parsed last-published manifest, or null when it could not be obtained. */
18
+ manifest: Record<string, unknown> | null;
19
+ /** Present when manifest is null: a human-readable reason to print. */
20
+ reason?: string;
21
+ /** Snapshot metadata, when found. */
22
+ meta?: {
23
+ store?: string;
24
+ version?: string;
25
+ fetchedAt?: string;
26
+ };
27
+ }
28
+ export interface FetchPriorManifestOptions {
29
+ /** BFF base URL, e.g. https://bff.extenshi.io (no trailing slash). */
30
+ bffUrl: string;
31
+ /** Numeric catalog extension ID. */
32
+ extensionId: string;
33
+ /** Optional `ek_` developer key — sent when the read path is gated. */
34
+ apiKey?: string;
35
+ /**
36
+ * Which store's snapshot to diff against. Permission sets differ per store, so
37
+ * pinning this avoids comparing a Chrome upload against, say, a Firefox
38
+ * snapshot. Omitted → the catalog returns the latest snapshot of any store.
39
+ */
40
+ store?: 'CHROME' | 'FIREFOX' | 'EDGE';
41
+ }
42
+ export declare function fetchPriorManifest(opts: FetchPriorManifestOptions): Promise<PriorManifestResult>;
43
+ //# sourceMappingURL=review-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-catalog.d.ts","sourceRoot":"","sources":["../src/review-catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,mBAAmB;IACnC,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACxC,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qCAAqC;IACrC,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/D;AAED,MAAM,WAAW,yBAAyB;IACzC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAA;IACd,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;CACrC;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiFtG"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * review-risk — fetch the last-published manifest for an extension from the
3
+ * Extenshi catalog so check 3 can diff against it. This is the part that is
4
+ * unique to us: we keep per-extension manifest snapshots, so we can tell you
5
+ * whether *this* update adds an auto-disabling permission versus what's live.
6
+ *
7
+ * Talks to the public BFF tRPC gateway:
8
+ * GET {bffUrl}/api/trpc/store.getLatestPublishedManifest?input=<json>
9
+ *
10
+ * The BFF read path may be gated behind a developer API key, so we send the
11
+ * `ek_` key when the caller has one. Everything here is fail-soft: any problem
12
+ * (key required, extension unknown, catalog older than this CLI, network error)
13
+ * resolves to `{ manifest: null, reason }` — the command then runs every other
14
+ * check and prints why the diff was skipped, rather than failing the run.
15
+ */
16
+ import { fetch } from 'undici';
17
+ const FETCH_TIMEOUT_MS = 15_000;
18
+ export async function fetchPriorManifest(opts) {
19
+ const id = Number(opts.extensionId);
20
+ if (!Number.isInteger(id) || id <= 0) {
21
+ return {
22
+ manifest: null,
23
+ reason: `invalid --extension-id "${opts.extensionId}" (expected a positive number)`,
24
+ };
25
+ }
26
+ const query = opts.store ? { extensionId: id, store: opts.store } : { extensionId: id };
27
+ const input = encodeURIComponent(JSON.stringify(query));
28
+ const url = `${opts.bffUrl}/api/trpc/store.getLatestPublishedManifest?input=${input}`;
29
+ let res;
30
+ try {
31
+ res = await fetch(url, {
32
+ headers: opts.apiKey ? { authorization: `Bearer ${opts.apiKey}` } : {},
33
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
34
+ });
35
+ }
36
+ catch (err) {
37
+ const e = err;
38
+ const why = e.name === 'TimeoutError' ? `timed out after ${FETCH_TIMEOUT_MS / 1000}s` : e.message;
39
+ return { manifest: null, reason: `could not reach the catalog (${why})` };
40
+ }
41
+ if (res.status === 401) {
42
+ return {
43
+ manifest: null,
44
+ reason: 'the catalog manifest read is gated — set EXTENSHI_API_KEY (run `extenshi login`) to enable the diff',
45
+ };
46
+ }
47
+ if (res.status === 404) {
48
+ return {
49
+ manifest: null,
50
+ reason: 'the deployed catalog API predates this feature (no getLatestPublishedManifest) — update once it ships',
51
+ };
52
+ }
53
+ if (!res.ok) {
54
+ return { manifest: null, reason: `catalog returned HTTP ${res.status}` };
55
+ }
56
+ let body;
57
+ try {
58
+ body = await res.json();
59
+ }
60
+ catch {
61
+ return { manifest: null, reason: 'catalog returned a non-JSON response' };
62
+ }
63
+ // tRPC (no transformer): { result: { data: <payload> } }, or { error: {...} }.
64
+ const error = body.error;
65
+ if (error) {
66
+ return { manifest: null, reason: `catalog error: ${error.message ?? 'unknown'}` };
67
+ }
68
+ const data = body.result?.data;
69
+ if (!data || data.manifest == null || typeof data.manifest !== 'object') {
70
+ const reason = data?.reason === 'no_snapshot'
71
+ ? 'no published manifest on record for this extension yet'
72
+ : data?.reason === 'manifest_unresolved'
73
+ ? 'the last snapshot could not be resolved to a manifest'
74
+ : 'the catalog returned no manifest for this extension';
75
+ return { manifest: null, reason };
76
+ }
77
+ return {
78
+ manifest: data.manifest,
79
+ meta: { store: data.store, version: data.version, fetchedAt: data.fetchedAt },
80
+ };
81
+ }
82
+ //# sourceMappingURL=review-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-catalog.js","sourceRoot":"","sources":["../src/review-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * review-risk — pure check logic for the pre-publish "will the store reject /
3
+ * slow-walk / silently disable this?" suite.
4
+ *
5
+ * Every finding maps to ONE of three real-world consequences, never a generic
6
+ * lint level:
7
+ *
8
+ * REJECTED — the store will reject the submission (you cannot ship as-is).
9
+ * SLOW — it ships, but review moves from <24h to several days.
10
+ * ATTRITION — it ships and passes review, but installed users are silently
11
+ * dropped on the update until they re-accept a new permission.
12
+ *
13
+ * Each check's `citation` points to the relevant official Chrome Web Store /
14
+ * Chrome for Developers documentation so the user can verify the rule at the
15
+ * source. (We do not cite third-party books in product output.)
16
+ *
17
+ * This module is PURE (no I/O) so the rules are unit-testable against fixtures.
18
+ * Archive extraction lives in review-archive.ts; the network manifest fetch in
19
+ * review-catalog.ts; rendering in review-render.ts.
20
+ */
21
+ export type Verdict = 'REJECTED' | 'SLOW' | 'ATTRITION';
22
+ export interface ReviewFinding {
23
+ /** The real-world consequence — drives the label shown to the user. */
24
+ verdict: Verdict;
25
+ /** Stable machine id (for --json consumers / suppression later). */
26
+ check: string;
27
+ /** One-line headline. */
28
+ title: string;
29
+ /** Why it matters, in plain language. */
30
+ detail: string;
31
+ /** The offending value or `file:line`, when there is one. */
32
+ evidence?: string;
33
+ /** The concrete fix. */
34
+ recommendation: string;
35
+ /** Official Chrome documentation backing the rule (shown to the user). */
36
+ citation: string;
37
+ }
38
+ /** A parsed manifest.json — only the fields the checks read are typed. */
39
+ export interface Manifest {
40
+ manifest_version?: number;
41
+ name?: string;
42
+ version?: string;
43
+ permissions?: unknown;
44
+ optional_permissions?: unknown;
45
+ host_permissions?: unknown;
46
+ optional_host_permissions?: unknown;
47
+ content_scripts?: Array<{
48
+ matches?: unknown;
49
+ js?: unknown;
50
+ [k: string]: unknown;
51
+ }>;
52
+ background?: {
53
+ service_worker?: string;
54
+ scripts?: unknown;
55
+ page?: string;
56
+ type?: string;
57
+ [k: string]: unknown;
58
+ };
59
+ action?: {
60
+ default_popup?: string;
61
+ [k: string]: unknown;
62
+ };
63
+ browser_action?: {
64
+ default_popup?: string;
65
+ [k: string]: unknown;
66
+ };
67
+ options_ui?: {
68
+ page?: string;
69
+ [k: string]: unknown;
70
+ };
71
+ options_page?: string;
72
+ side_panel?: {
73
+ default_path?: string;
74
+ [k: string]: unknown;
75
+ };
76
+ devtools_page?: string;
77
+ chrome_url_overrides?: Record<string, string>;
78
+ sandbox?: {
79
+ pages?: unknown;
80
+ [k: string]: unknown;
81
+ };
82
+ [k: string]: unknown;
83
+ }
84
+ /** A text file pulled out of the artifact: package-relative path → contents. */
85
+ export type FileMap = Map<string, string>;
86
+ export declare const PERMISSION_WARNINGS: Readonly<Record<string, string>>;
87
+ export declare function isGlobalHost(value: string): boolean;
88
+ /**
89
+ * Required API permissions only (host patterns stripped out). In MV2 hosts and
90
+ * API permissions share the `permissions` array, so we split by shape.
91
+ */
92
+ export declare function requiredApiPermissions(m: Manifest): string[];
93
+ /** Required host patterns: `host_permissions` (MV3) plus any host-shaped entry in `permissions` (MV2). */
94
+ export declare function requiredHostPermissions(m: Manifest): string[];
95
+ /** Normalise a manifest-declared path to the package-relative key used in the file map. */
96
+ export declare function normalizePath(p: string): string;
97
+ /**
98
+ * HTML pages the browser renders inside the extension's own CSP — popup,
99
+ * options, side panel, devtools, newtab/history/bookmarks overrides, sandbox
100
+ * pages, and the MV2 background page. These are exactly where inline scripts and
101
+ * eval get the extension rejected.
102
+ */
103
+ export declare function htmlEntrypoints(m: Manifest): string[];
104
+ export declare function checkSlowReviewQueue(m: Manifest): ReviewFinding[];
105
+ /**
106
+ * Static advisory — there is nothing in the package to inspect; it's a
107
+ * publishing-process fact developers routinely get burned by. Emitted once.
108
+ */
109
+ export declare function checkListingChangeReReview(): ReviewFinding[];
110
+ /**
111
+ * Diff the local manifest against the last-published one. A newly-added
112
+ * *required* permission that shows a warning silently disables the extension for
113
+ * the whole installed base on update (only a small toolbar icon appears) →
114
+ * silent attrition. Newly-added permissions of any kind also re-trip the slow
115
+ * review queue (ch.10).
116
+ *
117
+ * `prior` is the manifest fetched from the catalog's last snapshot; pass null
118
+ * when it could not be fetched (the caller surfaces why and this returns []).
119
+ */
120
+ export declare function checkAutoDisableOnUpdate(local: Manifest, prior: Manifest | null): ReviewFinding[];
121
+ export declare function checkRemoteCode(files: FileMap): ReviewFinding[];
122
+ export declare function checkHtmlCsp(m: Manifest, files: FileMap): ReviewFinding[];
123
+ export declare function checkServiceWorker(m: Manifest, files: FileMap): ReviewFinding[];
124
+ export declare function checkActiveTabAdvisor(m: Manifest): ReviewFinding[];
125
+ export interface ReviewInputs {
126
+ manifest: Manifest;
127
+ files: FileMap;
128
+ /** Last-published manifest from the catalog, or null when unavailable. */
129
+ priorManifest: Manifest | null;
130
+ }
131
+ export declare function runChecks(input: ReviewInputs): ReviewFinding[];
132
+ export interface ReviewSummary {
133
+ findings: ReviewFinding[];
134
+ counts: Record<Verdict, number>;
135
+ /** True when at least one finding will block publishing. */
136
+ blocking: boolean;
137
+ }
138
+ export declare function summarize(findings: ReviewFinding[]): ReviewSummary;
139
+ //# sourceMappingURL=review-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-checks.d.ts","sourceRoot":"","sources":["../src/review-checks.ts"],"names":[],"mappings":"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"}