@cosyte/x12 0.0.6 → 0.0.7

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/CHANGELOG.md CHANGED
@@ -42,8 +42,87 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
42
42
  a warning `message` is a frozen-registry lookup with positional metadata only, but an orphan is
43
43
  document content, verbatim, exactly like `tx.rawSegments`. Log `context` and `segmentIndex`.
44
44
 
45
+ ### Security
46
+
47
+ - **The PHI scanner refuses an in-scope entry that is not a regular file, on both of its enumerating
48
+ routes.** A symbolic link under a scan root pointing at a PHI-bearing file used to scan CLEAN on
49
+ both, so the pre-commit gate and CI both reported "no hits" over a capture the scan never read.
50
+ Measured on `5779542`, against a throwaway repository laid out like this one, using a synthetic
51
+ `.edi` payload whose NM1 person name, DMG date of birth, PER phone and `REF*SY` SSN are all hits at
52
+ exit 1 when the same bytes sit at a regular file:
53
+ - the all-mode walk enumerates `Dirent.isFile()`, which is an lstat answer, so a link is neither a
54
+ file nor a directory and fell out of the loop silently. A link under `test/fixtures`, a link
55
+ under `src/`, and a linked DIRECTORY (which takes a whole subtree with it) each reported
56
+ `OK - no hits` at exit 0;
57
+ - `--staged` reads content with `git show :<path>`, and git stores a link as its TARGET PATH under
58
+ mode `120000`, so that route was handed the path text and never the target's bytes. A staged
59
+ link reported `OK - no hits` at exit 0.
60
+
61
+ Both routes now refuse the scan (exit 2, the existing "could not complete" code) and name every
62
+ offender, not just the first. Neither route is made to FOLLOW an ENTRY it enumerated: following
63
+ would read bytes the enumeration does not control, and git does not carry those bytes anyway, so a
64
+ hit on them would be a claim about something no commit contains. That is a statement about an
65
+ entry, not about a scan ROOT: a walk root that is itself a link is still followed, because
66
+ `existsSync` and `readdirSync` both follow. Measured identically before and after this change, that
67
+ direction produces a superset scan rather than a blind one (the target's files are enumerated under
68
+ their in-root names and hit, exit 1), so it is deliberately left alone.
69
+
70
+ **A refusal names the entry's own repo-relative path and a scanner-owned token for its kind. It
71
+ never reports the link target**, which is working-tree text that can itself carry PHI: a target
72
+ path of the shape `<surname>-<given>-<dob>.edi` is the whole reason. That shape is written out
73
+ rather than shown, because a diagnostic about a PHI leak is itself a PHI surface. The concern was
74
+ not hypothetical here: measured at base, a staged link whose target name was a dashed-SSN shape
75
+ exited 1 and printed that shape, because `git show` handed the path text straight to the
76
+ cross-cutting shape pass.
77
+
78
+ **The `--staged` filter is now `AMT`, and `T` is the one-letter difference that made the mode check
79
+ reachable.** Replacing a TRACKED regular file with a link is neither an add nor a modify: measured
80
+ on this tree, `git diff --cached --raw --diff-filter=AM` returned zero rows for that change while
81
+ the unfiltered `--raw` showed `:100644 120000 <sha> <sha> T`. Without `T` the record died before
82
+ any mode could be read and the hook passed a mode-`120000` blob green. Admitting `T` also covers
83
+ the reverse typechange, a link replaced by a real file bearing PHI. The route reads
84
+ `git diff --cached --raw -z` rather than `--name-only` because the destination mode is the only
85
+ thing that distinguishes a staged regular file from a staged link or gitlink, and
86
+ `git show :<path>` answers all three without complaint. A record that does not parse refuses rather
87
+ than being skipped.
88
+
89
+ **Each route keeps its own existing boundary**: the walk still excludes a gitignored entry (the same
90
+ rule that already excludes a gitignored file), and `--staged` still looks only at
91
+ `test/fixtures/**` and `src/**.ts`. This narrows what those scopes admit; it does not widen them.
92
+ A gitlink under a scanned prefix already exited 2 before this change, but by `git show` failing and
93
+ echoing git's own text; it is now refused at enumeration and named by kind.
94
+
95
+ **`paths` mode is deliberately unchanged, because it was never blind**: it reads with
96
+ `readFileSync`, which follows a link, so an explicitly named path that is a link to a PHI-bearing
97
+ file is scanned and hits (measured, exit 1).
98
+
99
+ **Not closed here, and stated rather than implied**: `R` (rename) and `C` (copy) are still not
100
+ enumerated by `--staged` at all, which is pre-existing and needs the two-path `--raw` record shape
101
+ handled. Measured, so the cost is not left to inference: renaming a fixture while substituting a
102
+ real name stages as `:100644 100644 <sha> <sha> R080 <old> <new>`, which both `AM` and `AMT` return
103
+ zero rows for, and `--staged` exits 0 over a payload that is a hit as an ordinary add; `git mv` of
104
+ an already-committed link into `test/fixtures/` is `R100` and is likewise not refused. The all-mode
105
+ sweep is the backstop for both (exit 1 and exit 2 respectively), so the gap is at pre-commit, not
106
+ in CI. Also unclosed: a scan that observed nothing is still reported clean rather than refused; and
107
+ the
108
+ enumerate-then-read window in all mode is untouched, because tolerating a failed read pulls the
109
+ opposite way from narrowing what the enumeration admits and belongs in its own change. No library
110
+ code changed and no published type changed.
111
+
45
112
  ### Fixed
46
113
 
114
+ - **The `attw` publish gate no longer passes a tarball that carries no type declarations.** The
115
+ `attw` script was the bare CLI, and `@arethetypeswrong/cli` returns 0 whenever its analysis found
116
+ no types at all, before it reads the problem list. For a package that ships types, "This package
117
+ does not contain types." means the declarations were missing from the tarball, which is a broken
118
+ publish that the gate reported as a pass. Reproduced against this package with no concurrency
119
+ involved: with `dist/` removed, and with only `dist/index.d.ts` and `dist/index.d.cts` removed,
120
+ the CLI printed that sentence and exited 0 in both cases. The second is a state every build passes
121
+ through, because `tsup` writes the JS before the declarations (measured at 1.92 seconds apart on
122
+ one clean build here). `pnpm attw` now runs `scripts/attw.mjs`, which checks that every relative
123
+ path `package.json` promises exists and is non-empty before invoking the CLI, and fails afterwards
124
+ if the CLI still reports an untyped package. No change to the library or to any published type.
125
+
47
126
  - **A `defineProfile()` refusal message no longer grows with the value you passed in.** Twelve
48
127
  refusal sites in `src/profiles/validate.ts` hold twenty-three caller-value holes between them, and
49
128
  every one now routes through `renderCallerValue` or `renderCallerJson`. Re-derived on this tree
package/dist/index.cjs CHANGED
@@ -9892,7 +9892,7 @@ var profiles = Object.freeze({
9892
9892
  });
9893
9893
 
9894
9894
  // src/index.ts
9895
- var VERSION = "0.0.6";
9895
+ var VERSION = "0.0.7";
9896
9896
 
9897
9897
  exports.ACK_BUILD_ERROR_CODES = ACK_BUILD_ERROR_CODES;
9898
9898
  exports.ALL_WARNING_MESSAGES = ALL_WARNING_MESSAGES;