@endora-commerce/cli 0.100.0
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/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/bin/endora.d.ts +28 -0
- package/dist/bin/endora.d.ts.map +1 -0
- package/dist/bin/endora.js +926 -0
- package/dist/bin/endora.js.map +1 -0
- package/dist/check/estate.d.ts +189 -0
- package/dist/check/estate.d.ts.map +1 -0
- package/dist/check/estate.js +1037 -0
- package/dist/check/estate.js.map +1 -0
- package/dist/check/hosts.d.ts +25 -0
- package/dist/check/hosts.d.ts.map +1 -0
- package/dist/check/hosts.js +1347 -0
- package/dist/check/hosts.js.map +1 -0
- package/dist/check/index.d.ts +60 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +111 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/layout.d.ts +136 -0
- package/dist/check/layout.d.ts.map +1 -0
- package/dist/check/layout.js +262 -0
- package/dist/check/layout.js.map +1 -0
- package/dist/check/ledger.d.ts +98 -0
- package/dist/check/ledger.d.ts.map +1 -0
- package/dist/check/ledger.js +173 -0
- package/dist/check/ledger.js.map +1 -0
- package/dist/check/peer-owners.d.ts +116 -0
- package/dist/check/peer-owners.d.ts.map +1 -0
- package/dist/check/peer-owners.js +225 -0
- package/dist/check/peer-owners.js.map +1 -0
- package/dist/check/report.d.ts +33 -0
- package/dist/check/report.d.ts.map +1 -0
- package/dist/check/report.js +107 -0
- package/dist/check/report.js.map +1 -0
- package/dist/check/run.d.ts +147 -0
- package/dist/check/run.d.ts.map +1 -0
- package/dist/check/run.js +111 -0
- package/dist/check/run.js.map +1 -0
- package/dist/checks.d.ts +17 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +17 -0
- package/dist/checks.js.map +1 -0
- package/dist/dev/index.d.ts +83 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +298 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/generate/divergence.d.ts +38 -0
- package/dist/generate/divergence.d.ts.map +1 -0
- package/dist/generate/divergence.js +237 -0
- package/dist/generate/divergence.js.map +1 -0
- package/dist/generate/index.d.ts +90 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +369 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/declaration.d.ts +18 -0
- package/dist/inputs/declaration.d.ts.map +1 -0
- package/dist/inputs/declaration.js +64 -0
- package/dist/inputs/declaration.js.map +1 -0
- package/dist/inputs/env-file.d.ts +73 -0
- package/dist/inputs/env-file.d.ts.map +1 -0
- package/dist/inputs/env-file.js +134 -0
- package/dist/inputs/env-file.js.map +1 -0
- package/dist/inputs/prompt.d.ts +21 -0
- package/dist/inputs/prompt.d.ts.map +1 -0
- package/dist/inputs/prompt.js +59 -0
- package/dist/inputs/prompt.js.map +1 -0
- package/dist/inputs/resolve.d.ts +163 -0
- package/dist/inputs/resolve.d.ts.map +1 -0
- package/dist/inputs/resolve.js +290 -0
- package/dist/inputs/resolve.js.map +1 -0
- package/dist/install/host.d.ts +27 -0
- package/dist/install/host.d.ts.map +1 -0
- package/dist/install/host.js +90 -0
- package/dist/install/host.js.map +1 -0
- package/dist/install/index.d.ts +173 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +793 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/wizard.d.ts +144 -0
- package/dist/install/wizard.d.ts.map +1 -0
- package/dist/install/wizard.js +362 -0
- package/dist/install/wizard.js.map +1 -0
- package/dist/lib/admin-artefacts.d.ts +70 -0
- package/dist/lib/admin-artefacts.d.ts.map +1 -0
- package/dist/lib/admin-artefacts.js +354 -0
- package/dist/lib/admin-artefacts.js.map +1 -0
- package/dist/lib/admin-surfaces.d.ts +298 -0
- package/dist/lib/admin-surfaces.d.ts.map +1 -0
- package/dist/lib/admin-surfaces.js +669 -0
- package/dist/lib/admin-surfaces.js.map +1 -0
- package/dist/lib/delegated-composer.d.ts +85 -0
- package/dist/lib/delegated-composer.d.ts.map +1 -0
- package/dist/lib/delegated-composer.js +241 -0
- package/dist/lib/delegated-composer.js.map +1 -0
- package/dist/lib/divergence-artefacts.d.ts +305 -0
- package/dist/lib/divergence-artefacts.d.ts.map +1 -0
- package/dist/lib/divergence-artefacts.js +828 -0
- package/dist/lib/divergence-artefacts.js.map +1 -0
- package/dist/lib/divergence.d.ts +337 -0
- package/dist/lib/divergence.d.ts.map +1 -0
- package/dist/lib/divergence.js +1005 -0
- package/dist/lib/divergence.js.map +1 -0
- package/dist/lib/docs-artefacts.d.ts +395 -0
- package/dist/lib/docs-artefacts.d.ts.map +1 -0
- package/dist/lib/docs-artefacts.js +781 -0
- package/dist/lib/docs-artefacts.js.map +1 -0
- package/dist/lib/emitted-exports.d.ts +21 -0
- package/dist/lib/emitted-exports.d.ts.map +1 -0
- package/dist/lib/emitted-exports.js +96 -0
- package/dist/lib/emitted-exports.js.map +1 -0
- package/dist/lib/emitted-freshness.d.ts +112 -0
- package/dist/lib/emitted-freshness.d.ts.map +1 -0
- package/dist/lib/emitted-freshness.js +288 -0
- package/dist/lib/emitted-freshness.js.map +1 -0
- package/dist/lib/entity-index-artefact.d.ts +95 -0
- package/dist/lib/entity-index-artefact.d.ts.map +1 -0
- package/dist/lib/entity-index-artefact.js +210 -0
- package/dist/lib/entity-index-artefact.js.map +1 -0
- package/dist/lib/instance-build-inputs.d.ts +108 -0
- package/dist/lib/instance-build-inputs.d.ts.map +1 -0
- package/dist/lib/instance-build-inputs.js +165 -0
- package/dist/lib/instance-build-inputs.js.map +1 -0
- package/dist/lib/module-docs.d.ts +473 -0
- package/dist/lib/module-docs.d.ts.map +1 -0
- package/dist/lib/module-docs.js +711 -0
- package/dist/lib/module-docs.js.map +1 -0
- package/dist/lib/module-package-subpaths.d.ts +56 -0
- package/dist/lib/module-package-subpaths.d.ts.map +1 -0
- package/dist/lib/module-package-subpaths.js +223 -0
- package/dist/lib/module-package-subpaths.js.map +1 -0
- package/dist/lib/module-packages.d.ts +200 -0
- package/dist/lib/module-packages.d.ts.map +1 -0
- package/dist/lib/module-packages.js +580 -0
- package/dist/lib/module-packages.js.map +1 -0
- package/dist/lib/module-population.d.ts +129 -0
- package/dist/lib/module-population.d.ts.map +1 -0
- package/dist/lib/module-population.js +172 -0
- package/dist/lib/module-population.js.map +1 -0
- package/dist/lib/module-roots.d.ts +337 -0
- package/dist/lib/module-roots.d.ts.map +1 -0
- package/dist/lib/module-roots.js +586 -0
- package/dist/lib/module-roots.js.map +1 -0
- package/dist/lib/nested-checkouts.d.ts +33 -0
- package/dist/lib/nested-checkouts.d.ts.map +1 -0
- package/dist/lib/nested-checkouts.js +160 -0
- package/dist/lib/nested-checkouts.js.map +1 -0
- package/dist/lib/platform-root.d.ts +43 -0
- package/dist/lib/platform-root.d.ts.map +1 -0
- package/dist/lib/platform-root.js +134 -0
- package/dist/lib/platform-root.js.map +1 -0
- package/dist/lib/platform-surface.d.ts +235 -0
- package/dist/lib/platform-surface.d.ts.map +1 -0
- package/dist/lib/platform-surface.js +393 -0
- package/dist/lib/platform-surface.js.map +1 -0
- package/dist/lib/port-registrations.d.ts +223 -0
- package/dist/lib/port-registrations.d.ts.map +1 -0
- package/dist/lib/port-registrations.js +532 -0
- package/dist/lib/port-registrations.js.map +1 -0
- package/dist/lib/read-size.d.ts +154 -0
- package/dist/lib/read-size.d.ts.map +1 -0
- package/dist/lib/read-size.js +182 -0
- package/dist/lib/read-size.js.map +1 -0
- package/dist/lib/registration-owners.d.ts +79 -0
- package/dist/lib/registration-owners.d.ts.map +1 -0
- package/dist/lib/registration-owners.js +77 -0
- package/dist/lib/registration-owners.js.map +1 -0
- package/dist/lib/release-index.d.ts +53 -0
- package/dist/lib/release-index.d.ts.map +1 -0
- package/dist/lib/release-index.js +162 -0
- package/dist/lib/release-index.js.map +1 -0
- package/dist/lib/repeating-timers.d.ts +79 -0
- package/dist/lib/repeating-timers.d.ts.map +1 -0
- package/dist/lib/repeating-timers.js +189 -0
- package/dist/lib/repeating-timers.js.map +1 -0
- package/dist/lib/source-text.d.ts +34 -0
- package/dist/lib/source-text.d.ts.map +1 -0
- package/dist/lib/source-text.js +80 -0
- package/dist/lib/source-text.js.map +1 -0
- package/dist/lib/specifiers.d.ts +20 -0
- package/dist/lib/specifiers.d.ts.map +1 -0
- package/dist/lib/specifiers.js +130 -0
- package/dist/lib/specifiers.js.map +1 -0
- package/dist/lib/sql-tables.d.ts +166 -0
- package/dist/lib/sql-tables.d.ts.map +1 -0
- package/dist/lib/sql-tables.js +464 -0
- package/dist/lib/sql-tables.js.map +1 -0
- package/dist/lib/switchable-modules.d.ts +54 -0
- package/dist/lib/switchable-modules.d.ts.map +1 -0
- package/dist/lib/switchable-modules.js +104 -0
- package/dist/lib/switchable-modules.js.map +1 -0
- package/dist/lib/tailwind-sources.d.ts +136 -0
- package/dist/lib/tailwind-sources.d.ts.map +1 -0
- package/dist/lib/tailwind-sources.js +307 -0
- package/dist/lib/tailwind-sources.js.map +1 -0
- package/dist/lib/ui-layer.d.ts +54 -0
- package/dist/lib/ui-layer.d.ts.map +1 -0
- package/dist/lib/ui-layer.js +57 -0
- package/dist/lib/ui-layer.js.map +1 -0
- package/dist/lib/workspace-packages.d.ts +186 -0
- package/dist/lib/workspace-packages.d.ts.map +1 -0
- package/dist/lib/workspace-packages.js +351 -0
- package/dist/lib/workspace-packages.js.map +1 -0
- package/dist/new-instance/deploy.d.ts +211 -0
- package/dist/new-instance/deploy.d.ts.map +1 -0
- package/dist/new-instance/deploy.js +1381 -0
- package/dist/new-instance/deploy.js.map +1 -0
- package/dist/new-instance/docs-toolchain.d.ts +66 -0
- package/dist/new-instance/docs-toolchain.d.ts.map +1 -0
- package/dist/new-instance/docs-toolchain.js +69 -0
- package/dist/new-instance/docs-toolchain.js.map +1 -0
- package/dist/new-instance/host.d.ts +124 -0
- package/dist/new-instance/host.d.ts.map +1 -0
- package/dist/new-instance/host.js +276 -0
- package/dist/new-instance/host.js.map +1 -0
- package/dist/new-instance/index.d.ts +118 -0
- package/dist/new-instance/index.d.ts.map +1 -0
- package/dist/new-instance/index.js +567 -0
- package/dist/new-instance/index.js.map +1 -0
- package/dist/new-instance/modules.d.ts +188 -0
- package/dist/new-instance/modules.d.ts.map +1 -0
- package/dist/new-instance/modules.js +392 -0
- package/dist/new-instance/modules.js.map +1 -0
- package/dist/new-instance/template.d.ts +505 -0
- package/dist/new-instance/template.d.ts.map +1 -0
- package/dist/new-instance/template.js +1886 -0
- package/dist/new-instance/template.js.map +1 -0
- package/dist/new-module/emit.d.ts +67 -0
- package/dist/new-module/emit.d.ts.map +1 -0
- package/dist/new-module/emit.js +1393 -0
- package/dist/new-module/emit.js.map +1 -0
- package/dist/new-module/host.d.ts +67 -0
- package/dist/new-module/host.d.ts.map +1 -0
- package/dist/new-module/host.js +224 -0
- package/dist/new-module/host.js.map +1 -0
- package/dist/new-module/index.d.ts +32 -0
- package/dist/new-module/index.d.ts.map +1 -0
- package/dist/new-module/index.js +193 -0
- package/dist/new-module/index.js.map +1 -0
- package/dist/new-module/spec.d.ts +188 -0
- package/dist/new-module/spec.d.ts.map +1 -0
- package/dist/new-module/spec.js +404 -0
- package/dist/new-module/spec.js.map +1 -0
- package/dist/new-module/text.d.ts +15 -0
- package/dist/new-module/text.d.ts.map +1 -0
- package/dist/new-module/text.js +22 -0
- package/dist/new-module/text.js.map +1 -0
- package/dist/new-storefront/dockerfile.d.ts +20 -0
- package/dist/new-storefront/dockerfile.d.ts.map +1 -0
- package/dist/new-storefront/dockerfile.js +131 -0
- package/dist/new-storefront/dockerfile.js.map +1 -0
- package/dist/new-storefront/gitignore.d.ts +23 -0
- package/dist/new-storefront/gitignore.d.ts.map +1 -0
- package/dist/new-storefront/gitignore.js +39 -0
- package/dist/new-storefront/gitignore.js.map +1 -0
- package/dist/new-storefront/index.d.ts +93 -0
- package/dist/new-storefront/index.d.ts.map +1 -0
- package/dist/new-storefront/index.js +329 -0
- package/dist/new-storefront/index.js.map +1 -0
- package/dist/new-storefront/npmrc.d.ts +98 -0
- package/dist/new-storefront/npmrc.d.ts.map +1 -0
- package/dist/new-storefront/npmrc.js +217 -0
- package/dist/new-storefront/npmrc.js.map +1 -0
- package/dist/new-storefront/reference.d.ts +189 -0
- package/dist/new-storefront/reference.d.ts.map +1 -0
- package/dist/new-storefront/reference.js +430 -0
- package/dist/new-storefront/reference.js.map +1 -0
- package/dist/new-storefront/rewrite.d.ts +171 -0
- package/dist/new-storefront/rewrite.d.ts.map +1 -0
- package/dist/new-storefront/rewrite.js +701 -0
- package/dist/new-storefront/rewrite.js.map +1 -0
- package/dist/release-index.json +284 -0
- package/dist/rules/action-route-permissions.d.ts +141 -0
- package/dist/rules/action-route-permissions.d.ts.map +1 -0
- package/dist/rules/action-route-permissions.js +556 -0
- package/dist/rules/action-route-permissions.js.map +1 -0
- package/dist/rules/bundle-pairing.d.ts +74 -0
- package/dist/rules/bundle-pairing.d.ts.map +1 -0
- package/dist/rules/bundle-pairing.js +281 -0
- package/dist/rules/bundle-pairing.js.map +1 -0
- package/dist/rules/channel-resolution.d.ts +17 -0
- package/dist/rules/channel-resolution.d.ts.map +1 -0
- package/dist/rules/channel-resolution.js +382 -0
- package/dist/rules/channel-resolution.js.map +1 -0
- package/dist/rules/command-coverage.d.ts +210 -0
- package/dist/rules/command-coverage.d.ts.map +1 -0
- package/dist/rules/command-coverage.js +714 -0
- package/dist/rules/command-coverage.js.map +1 -0
- package/dist/rules/container-imports.d.ts +60 -0
- package/dist/rules/container-imports.d.ts.map +1 -0
- package/dist/rules/container-imports.js +158 -0
- package/dist/rules/container-imports.js.map +1 -0
- package/dist/rules/default-language-prose.d.ts +212 -0
- package/dist/rules/default-language-prose.d.ts.map +1 -0
- package/dist/rules/default-language-prose.js +710 -0
- package/dist/rules/default-language-prose.js.map +1 -0
- package/dist/rules/diacritic-folds.d.ts +238 -0
- package/dist/rules/diacritic-folds.d.ts.map +1 -0
- package/dist/rules/diacritic-folds.js +681 -0
- package/dist/rules/diacritic-folds.js.map +1 -0
- package/dist/rules/entity-tenant-classification.d.ts +171 -0
- package/dist/rules/entity-tenant-classification.d.ts.map +1 -0
- package/dist/rules/entity-tenant-classification.js +323 -0
- package/dist/rules/entity-tenant-classification.js.map +1 -0
- package/dist/rules/entry-presence.d.ts +142 -0
- package/dist/rules/entry-presence.d.ts.map +1 -0
- package/dist/rules/entry-presence.js +339 -0
- package/dist/rules/entry-presence.js.map +1 -0
- package/dist/rules/entry-scope.d.ts +91 -0
- package/dist/rules/entry-scope.d.ts.map +1 -0
- package/dist/rules/entry-scope.js +404 -0
- package/dist/rules/entry-scope.js.map +1 -0
- package/dist/rules/env-inputs.d.ts +222 -0
- package/dist/rules/env-inputs.d.ts.map +1 -0
- package/dist/rules/env-inputs.js +951 -0
- package/dist/rules/env-inputs.js.map +1 -0
- package/dist/rules/kernel-boundary.d.ts +37 -0
- package/dist/rules/kernel-boundary.d.ts.map +1 -0
- package/dist/rules/kernel-boundary.js +195 -0
- package/dist/rules/kernel-boundary.js.map +1 -0
- package/dist/rules/nul-bytes.d.ts +233 -0
- package/dist/rules/nul-bytes.d.ts.map +1 -0
- package/dist/rules/nul-bytes.js +332 -0
- package/dist/rules/nul-bytes.js.map +1 -0
- package/dist/rules/platform-surface.d.ts +479 -0
- package/dist/rules/platform-surface.d.ts.map +1 -0
- package/dist/rules/platform-surface.js +749 -0
- package/dist/rules/platform-surface.js.map +1 -0
- package/dist/rules/port-catches.d.ts +225 -0
- package/dist/rules/port-catches.d.ts.map +1 -0
- package/dist/rules/port-catches.js +1374 -0
- package/dist/rules/port-catches.js.map +1 -0
- package/dist/rules/port-shape.d.ts +213 -0
- package/dist/rules/port-shape.d.ts.map +1 -0
- package/dist/rules/port-shape.js +670 -0
- package/dist/rules/port-shape.js.map +1 -0
- package/dist/rules/queue-names.d.ts +108 -0
- package/dist/rules/queue-names.d.ts.map +1 -0
- package/dist/rules/queue-names.js +395 -0
- package/dist/rules/queue-names.js.map +1 -0
- package/dist/rules/singleton-identity.d.ts +205 -0
- package/dist/rules/singleton-identity.d.ts.map +1 -0
- package/dist/rules/singleton-identity.js +830 -0
- package/dist/rules/singleton-identity.js.map +1 -0
- package/dist/rules/subscribe-seam.d.ts +121 -0
- package/dist/rules/subscribe-seam.d.ts.map +1 -0
- package/dist/rules/subscribe-seam.js +594 -0
- package/dist/rules/subscribe-seam.js.map +1 -0
- package/dist/rules/transaction-context.d.ts +40 -0
- package/dist/rules/transaction-context.d.ts.map +1 -0
- package/dist/rules/transaction-context.js +294 -0
- package/dist/rules/transaction-context.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI check — no source file in this repository carries a raw NUL byte (issue #190).
|
|
3
|
+
*
|
|
4
|
+
* ## Why a byte deserves its own check
|
|
5
|
+
*
|
|
6
|
+
* The artefact that would reveal this defect **is the diff itself**. Git's
|
|
7
|
+
* content filter classifies a blob as binary when it finds a NUL in it, and from
|
|
8
|
+
* that moment every diff of the file reads `Binary files a/… and b/… differ`.
|
|
9
|
+
* The file stops being reviewable: `git diff`, `git blame -L`, the MR widget and
|
|
10
|
+
* every review UI show nothing at all. So the one thing that would have caught
|
|
11
|
+
* the byte during review is the thing the byte switches off.
|
|
12
|
+
*
|
|
13
|
+
* That is not hypothetical. Six files in this tree spelled a NUL separator as a
|
|
14
|
+
* raw byte inside a template literal — `media-ingestor.ts` (issue #182) plus the
|
|
15
|
+
* five issue #190 names — and each survived every review of every commit that
|
|
16
|
+
* touched it, because none of those commits could be read.
|
|
17
|
+
*
|
|
18
|
+
* The separator itself is correct in all six: NUL is the one byte the joined
|
|
19
|
+
* fields cannot contain, which is exactly what a join separator has to be. The
|
|
20
|
+
* defect is never the byte's *value*, only how the **source** spells it. Write
|
|
21
|
+
* `\0` (or `\x00`) and the compiled string is identical to the last bit while
|
|
22
|
+
* the source stays text.
|
|
23
|
+
*
|
|
24
|
+
* ## Anywhere in the file, not just where git looks
|
|
25
|
+
*
|
|
26
|
+
* Git only reads the **first 8000 bytes** when it decides binary-or-not. The NUL
|
|
27
|
+
* in `admin_actions/services/admin-actions-service.ts` sat at byte 8032, so git
|
|
28
|
+
* kept diffing that file as text and only `file(1)` disagreed — the byte was
|
|
29
|
+
* still there, still one edit away from crossing the window, and still invisible
|
|
30
|
+
* to every tool that does not share git's heuristic. A rule that copied git's
|
|
31
|
+
* window would have declared that file clean. This check reads the whole file.
|
|
32
|
+
*
|
|
33
|
+
* ## Only NUL
|
|
34
|
+
*
|
|
35
|
+
* The other C0 control characters are not in scope, deliberately. A raw `\x1f`
|
|
36
|
+
* is unpleasant but it does not change how any tool classifies the file: the
|
|
37
|
+
* diff still renders, review still works, and the ratchet this check installs
|
|
38
|
+
* would be claiming more than the failure it was written for. NUL is the byte
|
|
39
|
+
* with the tooling consequence, so NUL is the byte with the rule.
|
|
40
|
+
*
|
|
41
|
+
* ## The population, and how it fails
|
|
42
|
+
*
|
|
43
|
+
* Every file under the repository root **except** the two exclusions declared
|
|
44
|
+
* below, each with its reason:
|
|
45
|
+
*
|
|
46
|
+
* - `SKIPPED_DIRECTORIES` — trees that are not this repository's source.
|
|
47
|
+
* - `GENERATED_FILE_EXTENSIONS` — tool output written beside the source it
|
|
48
|
+
* came from, so no directory prune reaches it.
|
|
49
|
+
* - `BINARY_EXTENSIONS` and `BINARY_FILENAMES` — file types whose content is
|
|
50
|
+
* bytes by definition. A PNG is not a source file with a NUL problem; it is
|
|
51
|
+
* not a source file.
|
|
52
|
+
*
|
|
53
|
+
* The exclusion is a **deny-list on purpose**. An allow-list of known-text
|
|
54
|
+
* extensions fails open: the next `.sql`, `.toml` or extension-less script to
|
|
55
|
+
* arrive would be silently unscanned, and nothing would report it. With a
|
|
56
|
+
* deny-list a new file type is scanned by default, and a genuinely binary one
|
|
57
|
+
* announces itself by failing this check once — at which point it is added here
|
|
58
|
+
* with a reason rather than to a silent skip.
|
|
59
|
+
*
|
|
60
|
+
* The cost of a *missing* exclusion is therefore work rather than correctness,
|
|
61
|
+
* and it is real work: `.docusaurus` and `backend/var/assets` were not declared,
|
|
62
|
+
* so a working tree that had built the docs site and served one upload scanned
|
|
63
|
+
* 8288 files where a clean checkout scans 5165 — three thousand reads of output
|
|
64
|
+
* nobody wrote, and a NUL among them would have been reported against a path no
|
|
65
|
+
* merge request can change (issue #248). The candidates come from `.gitignore`:
|
|
66
|
+
* a tree git is told not to track is a tree this repository does not author.
|
|
67
|
+
*
|
|
68
|
+
* **Which of the two tables an exclusion belongs in is decided by its name.**
|
|
69
|
+
* `SKIPPED_DIRECTORIES` prunes a *name* wherever it occurs, so a name earns a
|
|
70
|
+
* place there only when it names its own producer (`node_modules`, `.next`,
|
|
71
|
+
* `storybook-static`) or is a dot-prefixed tool directory (`.turbo`, `.vite`).
|
|
72
|
+
* A generic word is somebody's plausible source directory too, and pruning it
|
|
73
|
+
* everywhere would take a subtree out of the scan for a name rather than for a
|
|
74
|
+
* reason — so `backend/var` is anchored at the one path it occupies, in
|
|
75
|
+
* `SKIPPED_PATH_PREFIXES`.
|
|
76
|
+
*
|
|
77
|
+
* Three `.gitignore` entries from the same sweep are deliberately **not**
|
|
78
|
+
* declared: `out/`, `tmp/` and `uploads/`. Each is a bare generic word, none
|
|
79
|
+
* held a single file in the measured tree, and an exclusion that buys no reads
|
|
80
|
+
* buys only the chance of taking a future source directory out of the scan. The
|
|
81
|
+
* deny-list is what makes that the safe order to be wrong in: an undeclared
|
|
82
|
+
* tree costs reads, a wrongly declared one costs coverage, so a name arrives
|
|
83
|
+
* here when it has been measured to matter and not before.
|
|
84
|
+
*
|
|
85
|
+
* A text file that genuinely must keep a NUL — a fixture whose whole point is a
|
|
86
|
+
* real NUL arriving in real data — goes in `NUL_BYTES_ALLOWED` with a reason.
|
|
87
|
+
* That ledger is **two-way**: an unledgered NUL fails the build, and a ledger
|
|
88
|
+
* entry naming a file that no longer has one fails it too. It is empty; the five
|
|
89
|
+
* issue #190 files were all repaired rather than ledgered, because in every one
|
|
90
|
+
* of them the escape produces the same string at runtime and loses nothing.
|
|
91
|
+
*
|
|
92
|
+
* ## One analysis, two hosts
|
|
93
|
+
*
|
|
94
|
+
* This file is the analysis. `backend/scripts/check-nul-bytes.ts` hosts it over
|
|
95
|
+
* this repository, and `endora check` hosts it over one module package
|
|
96
|
+
* (`specs/101-endora-check/contracts/package-scope-layout.md` §6). Neither host
|
|
97
|
+
* re-derives the other's population, and the walk each performs is its own —
|
|
98
|
+
* what they share is {@link isScannablePath}, which is the rule.
|
|
99
|
+
*/
|
|
100
|
+
/**
|
|
101
|
+
* Directory names pruned wherever they occur, and why each is not source.
|
|
102
|
+
*
|
|
103
|
+
* Declared rather than hard-coded into the walk so that the reason travels with
|
|
104
|
+
* the exclusion: a directory skipped here is a directory this check makes no
|
|
105
|
+
* claim about, and the next reader gets to see which claim was dropped.
|
|
106
|
+
*/
|
|
107
|
+
export const SKIPPED_DIRECTORIES = {
|
|
108
|
+
'.git': "Git's own object store — every pack file is binary by construction.",
|
|
109
|
+
node_modules: "Installed dependencies: third-party bytes, not this repository's source.",
|
|
110
|
+
dist: 'Build output, reproduced from source by the build.',
|
|
111
|
+
build: 'Build output, reproduced from source by the build.',
|
|
112
|
+
'.next': "Next.js build output, reproduced from the storefront's source.",
|
|
113
|
+
coverage: 'Coverage report output, regenerated by every run.',
|
|
114
|
+
'.pnpm-store': "pnpm's content-addressed package store.",
|
|
115
|
+
'test-results': 'Playwright run output, regenerated by every run.',
|
|
116
|
+
'playwright-report': 'Playwright report output, regenerated by every run.',
|
|
117
|
+
'blob-report': 'Playwright shard output, merged into the report and then discarded.',
|
|
118
|
+
'.playwright': "Playwright's per-run state directory.",
|
|
119
|
+
'.docusaurus': "Docusaurus' generated route data and build cache, written beside the docs " +
|
|
120
|
+
'site it is generated from. The one this check was measured missing: a tree ' +
|
|
121
|
+
'that had built the site scanned it as source (issue #248).',
|
|
122
|
+
'storybook-static': 'Storybook build output, reproduced from the stories by the build.',
|
|
123
|
+
'.nyc_output': 'Coverage instrumentation output — the raw half of `coverage/`.',
|
|
124
|
+
'.turbo': "Turborepo's task cache.",
|
|
125
|
+
'.vite': "Vite's dependency pre-bundling cache.",
|
|
126
|
+
'.swc': "SWC's compilation cache.",
|
|
127
|
+
'.cache': 'A tool cache by name — the dot-prefixed convention for exactly that.',
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Repo-relative directory prefixes that are not this checkout, keyed by prefix
|
|
131
|
+
* with the reason as the value — the same discipline as `SKIPPED_DIRECTORIES`,
|
|
132
|
+
* but path-anchored rather than name-anchored.
|
|
133
|
+
*
|
|
134
|
+
* `SKIPPED_DIRECTORIES` matches a *name* anywhere in the tree, which is right
|
|
135
|
+
* for `node_modules` and wrong here: `.claude/` also holds `agents/` and
|
|
136
|
+
* `skills/`, which are tracked repository source and must stay scanned. Only
|
|
137
|
+
* the worktree root is excluded. The same reasoning puts every generic-word
|
|
138
|
+
* exclusion here rather than there — see the header.
|
|
139
|
+
*/
|
|
140
|
+
export const SKIPPED_PATH_PREFIXES = {
|
|
141
|
+
'.claude/worktrees': 'Nested git worktrees — other commits of this same repository, each a ' +
|
|
142
|
+
'separate checkout with its own dependencies. Scanning them reports a ' +
|
|
143
|
+
'file already repaired on this commit, once per worktree, and reports it ' +
|
|
144
|
+
'against a path no merge request can change.',
|
|
145
|
+
'backend/var': "The backend's local variable-data root: the content-addressed asset store " +
|
|
146
|
+
'a running instance writes uploads and generated documents into. Three ' +
|
|
147
|
+
'thousand of them stood in the measured tree, none written by anybody, and ' +
|
|
148
|
+
'a NUL in an uploaded file is data rather than a defect. Path-anchored ' +
|
|
149
|
+
'because `var` is a generic word, not the name of a producer.',
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Extensions whose content is bytes by definition, and why.
|
|
153
|
+
*
|
|
154
|
+
* A file here is out of the population entirely — not exempted from the rule but
|
|
155
|
+
* outside it, because "a source file must not contain a NUL" says nothing about
|
|
156
|
+
* a PNG. Adding an entry is cheap and visible; the cost of getting it wrong is
|
|
157
|
+
* one file that stops being checked, which is why each carries a reason.
|
|
158
|
+
*/
|
|
159
|
+
export const BINARY_EXTENSIONS = {
|
|
160
|
+
'.png': 'Raster image — app icons and the Playwright visual snapshots.',
|
|
161
|
+
'.jpg': 'Raster image.',
|
|
162
|
+
'.jpeg': 'Raster image.',
|
|
163
|
+
'.gif': 'Raster image.',
|
|
164
|
+
'.webp': 'Raster image.',
|
|
165
|
+
'.avif': 'Raster image.',
|
|
166
|
+
'.ico': 'Icon bundle — a container of raster images.',
|
|
167
|
+
'.pdf': 'Portable Document Format — a compressed byte container.',
|
|
168
|
+
'.zip': 'Archive — a compressed byte container.',
|
|
169
|
+
'.gz': 'Compressed stream.',
|
|
170
|
+
'.woff': 'Web font — a compressed font container.',
|
|
171
|
+
'.woff2': 'Web font — a compressed font container.',
|
|
172
|
+
'.ttf': 'Font — glyph outlines in a binary table format.',
|
|
173
|
+
'.otf': 'Font — glyph outlines in a binary table format.',
|
|
174
|
+
'.eot': 'Font — glyph outlines in a binary table format.',
|
|
175
|
+
'.mp4': 'Video — an encoded media container.',
|
|
176
|
+
'.webm': 'Video — an encoded media container.',
|
|
177
|
+
'.wasm': 'WebAssembly module — a binary instruction format.',
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Exact file names that are binary, for the files that carry no extension.
|
|
181
|
+
*
|
|
182
|
+
* Separate from `BINARY_EXTENSIONS` because a leading dot is a dotfile marker,
|
|
183
|
+
* not an extension: `.gitignore` is text and must stay in the population, so a
|
|
184
|
+
* dot-named file cannot be classified by the same rule. Matched on the basename
|
|
185
|
+
* anywhere in the tree.
|
|
186
|
+
*/
|
|
187
|
+
export const BINARY_FILENAMES = {
|
|
188
|
+
'.thumbnail': 'Design-tool project thumbnail — a WebP bitmap the tool writes without an extension.',
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Extensions of **generated** files that a tool writes beside the source it was
|
|
192
|
+
* generated from, and why each is not this repository's source.
|
|
193
|
+
*
|
|
194
|
+
* A fourth category, and it exists because the other three cannot hold these
|
|
195
|
+
* honestly. `SKIPPED_DIRECTORIES` prunes a directory, and these files sit in a
|
|
196
|
+
* source directory rather than under a `dist/`. `BINARY_EXTENSIONS` says
|
|
197
|
+
* "bytes by definition", and a `.tsbuildinfo` is JSON — filing it there would
|
|
198
|
+
* put a false sentence in a reason field, which is the one thing this file's
|
|
199
|
+
* discipline cannot afford. `NUL_BYTES_ALLOWED` is for a file that *carries* a
|
|
200
|
+
* NUL and is right to.
|
|
201
|
+
*
|
|
202
|
+
* This is `.docusaurus`' case one granularity down. That entry exists because a
|
|
203
|
+
* tree that had built the docs site scanned it as source (issue #248); this one
|
|
204
|
+
* exists because a tree that has type-checked the storefront scans
|
|
205
|
+
* `tsconfig.tsbuildinfo` as source. Both are gitignored output a tool drops
|
|
206
|
+
* where it works.
|
|
207
|
+
*
|
|
208
|
+
* **The cost is not a false green** — a `.tsbuildinfo` holds no NUL, so nothing
|
|
209
|
+
* was being missed. It is that the file count moved on any tree where a
|
|
210
|
+
* type-check had run, and the estate's `read:` lines are what four Wave 4 merge
|
|
211
|
+
* requests used to prove a change touched nothing it should not. Two agents
|
|
212
|
+
* chased this `+1` to ground independently before it was written down. A
|
|
213
|
+
* verification tool whose baseline shifts under you is worth less than one that
|
|
214
|
+
* does not, which is the whole argument for the entry.
|
|
215
|
+
*/
|
|
216
|
+
export const GENERATED_FILE_EXTENSIONS = {
|
|
217
|
+
'.tsbuildinfo': "TypeScript's incremental build state, written beside the `tsconfig.json` it " +
|
|
218
|
+
'belongs to rather than into an output directory. Gitignored, reproduced by ' +
|
|
219
|
+
'the next `tsc`, and present or absent depending on whether anyone has run one.',
|
|
220
|
+
};
|
|
221
|
+
/**
|
|
222
|
+
* Text files allowed to keep a raw NUL, with the reason it is right.
|
|
223
|
+
*
|
|
224
|
+
* **Two-way**, in the idiom of `BARE_SUBSCRIPTIONS_TO_DRAIN`: an unledgered NUL
|
|
225
|
+
* fails the build, and an entry that no longer describes one fails it too.
|
|
226
|
+
*
|
|
227
|
+
* It is empty, and it should stay hard to add to. The obvious candidate — a
|
|
228
|
+
* hostile-input fixture — is not one: a fixture builds a JavaScript string, and
|
|
229
|
+
* `'\x00'` and a raw NUL byte produce the same string with the same code point,
|
|
230
|
+
* so escaping costs the fixture nothing and buys back the diff. An entry here
|
|
231
|
+
* has to name something the *file's bytes* do, not something its values do.
|
|
232
|
+
*/
|
|
233
|
+
export const NUL_BYTES_ALLOWED = {};
|
|
234
|
+
/** How many bytes of a blob git reads before deciding binary-or-text. */
|
|
235
|
+
export const GIT_BINARY_WINDOW = 8000;
|
|
236
|
+
const NUL = 0;
|
|
237
|
+
/** The extension of a path, lower-cased, including the dot; `''` when there is none. */
|
|
238
|
+
export function extensionOf(path) {
|
|
239
|
+
const base = path.slice(path.lastIndexOf('/') + 1);
|
|
240
|
+
const dot = base.lastIndexOf('.');
|
|
241
|
+
// A leading dot is a dotfile (`.gitignore`), not an extension.
|
|
242
|
+
if (dot <= 0)
|
|
243
|
+
return '';
|
|
244
|
+
return base.slice(dot).toLowerCase();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Whether a path is in the population.
|
|
248
|
+
*
|
|
249
|
+
* Path-based rather than walk-based so the two exclusions are provable from a
|
|
250
|
+
* synthetic path: the pruning a real run does for speed and the exclusion the
|
|
251
|
+
* rule makes are then the same decision, taken in one place.
|
|
252
|
+
*/
|
|
253
|
+
/**
|
|
254
|
+
* Is this repo-relative path at, or under, a `SKIPPED_PATH_PREFIXES` entry?
|
|
255
|
+
*
|
|
256
|
+
* **One function, called from both places on purpose.** The walk prunes for
|
|
257
|
+
* speed and `isScannablePath` states the rule, and while those were two
|
|
258
|
+
* expressions of the same predicate the walk's copy kept the check reporting
|
|
259
|
+
* `violations=0` after the rule's copy went missing — so the red proof, which
|
|
260
|
+
* enters at `findNulBytes`, could not see its own exclusion disappear. A
|
|
261
|
+
* duplicated decision is one that can go half-missing without anything
|
|
262
|
+
* noticing.
|
|
263
|
+
*/
|
|
264
|
+
export function isUnderSkippedPrefix(relativePath) {
|
|
265
|
+
return Object.keys(SKIPPED_PATH_PREFIXES).some((prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}/`));
|
|
266
|
+
}
|
|
267
|
+
export function isScannablePath(path) {
|
|
268
|
+
const segments = path.split('/');
|
|
269
|
+
if (segments.slice(0, -1).some((segment) => SKIPPED_DIRECTORIES[segment] !== undefined)) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
if (isUnderSkippedPrefix(path))
|
|
273
|
+
return false;
|
|
274
|
+
const basename = segments[segments.length - 1] ?? '';
|
|
275
|
+
if (BINARY_FILENAMES[basename] !== undefined)
|
|
276
|
+
return false;
|
|
277
|
+
const extension = extensionOf(path);
|
|
278
|
+
if (GENERATED_FILE_EXTENSIONS[extension] !== undefined)
|
|
279
|
+
return false;
|
|
280
|
+
return BINARY_EXTENSIONS[extension] === undefined;
|
|
281
|
+
}
|
|
282
|
+
/** Every NUL-carrying file among the scannable ones, first occurrence located. */
|
|
283
|
+
export function findNulBytes(files) {
|
|
284
|
+
const found = [];
|
|
285
|
+
for (const file of files) {
|
|
286
|
+
if (!isScannablePath(file.path))
|
|
287
|
+
continue;
|
|
288
|
+
const { bytes } = file;
|
|
289
|
+
let count = 0;
|
|
290
|
+
let first = -1;
|
|
291
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
292
|
+
if (bytes[i] === NUL) {
|
|
293
|
+
if (first === -1)
|
|
294
|
+
first = i;
|
|
295
|
+
count += 1;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (first === -1)
|
|
299
|
+
continue;
|
|
300
|
+
let line = 1;
|
|
301
|
+
let lineStart = 0;
|
|
302
|
+
for (let i = 0; i < first; i += 1) {
|
|
303
|
+
if (bytes[i] === 0x0a) {
|
|
304
|
+
line += 1;
|
|
305
|
+
lineStart = i + 1;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
found.push({
|
|
309
|
+
path: file.path,
|
|
310
|
+
byteOffset: first,
|
|
311
|
+
line,
|
|
312
|
+
column: first - lineStart + 1,
|
|
313
|
+
count,
|
|
314
|
+
beyondGitBinaryWindow: first >= GIT_BINARY_WINDOW,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
found.sort((a, b) => a.path.localeCompare(b.path));
|
|
318
|
+
return found;
|
|
319
|
+
}
|
|
320
|
+
export function checkNulBytes(files, ledger = NUL_BYTES_ALLOWED) {
|
|
321
|
+
const scannable = [...files].filter((file) => isScannablePath(file.path));
|
|
322
|
+
const all = findNulBytes(scannable);
|
|
323
|
+
const paths = new Set(all.map((finding) => finding.path));
|
|
324
|
+
return {
|
|
325
|
+
scanned: scannable.length,
|
|
326
|
+
total: all.length,
|
|
327
|
+
violations: all.filter((finding) => ledger[finding.path] === undefined),
|
|
328
|
+
ledgered: all.filter((finding) => ledger[finding.path] !== undefined),
|
|
329
|
+
stale: Object.keys(ledger).filter((path) => !paths.has(path)),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=nul-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nul-bytes.js","sourceRoot":"","sources":["../../src/rules/nul-bytes.ts"],"names":[],"mappings":"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"}
|