From 20b8435c1c78f5222881d7f261a0ab39e4e1226a Mon Sep 17 00:00:00 2001 From: Jake Sanders Date: Tue, 4 Aug 2026 15:29:50 -0700 Subject: [PATCH 1/2] package-firewall: add dependency-free JSON editing primitives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First code chunk of the VS Code ecosystem. Nothing calls these yet — they are added with their tests so the byte-fidelity properties can be reviewed on their own, ahead of the lifecycle that uses them. VS Code's product.json is the only config target here that is JSON, so it can carry neither a '#' sentinel nor an ${ENDOR_*} reference, and it must be edited in place with byte-exact restore. That rules out reserialization, and there is no jq or python3 guarantee on a stock macOS or a minimal Linux image, so these are line-oriented awk editors over the depth-1 object. plutil is not an option either: it reorders every top-level key and minifies, and `plutil -lint` does not even validate JSON. endor_b64url / endor_b64d base64url on stdin, matching endor_b64 endor_redact_ak strip the _ak/ path segment endor_file_has_final_newline endor_replace_contents_inplace preserves inode, mode, owner and the source's final-newline state endor_json_top_string depth-1 scalar, ignoring nested keys endor_json_extract_top_object raw lines of a depth-1 object endor_json_merge_object_keys key-level set and delete, commas recomputed endor_json_replace_top_object verbatim splice-back, for restore endor_json_insert_top_line / endor_json_remove_top_key endor_json_validate Two properties are the whole point, and both are asserted: - An edit touches only the keys it claims to. The patch is one key set and one removed; the diff against a pristine file is 3 lines, not a reserialized 2963. - Restore is byte-exact. Shipped product.json has no final newline while awk always emits one, so the newline state is normalised back on write — otherwise every patch would dirty the last line and no restore could ever match. Deleting or appending the last entry in an object must not leave a trailing comma, so the merge recomputes entry-terminating commas rather than editing lines in isolation. On input it cannot handle (minified, not line-oriented) each editor declines with a non-zero return and leaves the file untouched, rather than guessing. endor_json_validate also rejects trailing commas structurally: node is not always resolvable, and a trailing comma is precisely the malformation a bad comma rewrite produces. Tests: 43 assertions against a synthetic tests/fixtures/product.json — shaped like a shipped one (tab-indented, LF, no final newline, extensionsGallery at depth 1) but not tied to a VS Code build, so assertions like "16 accessSKUs" don't start failing on VS Code's release schedule. Also covers 4-space indentation, a sole-entry delete, and minified input. Co-Authored-By: Claude Opus 5 (1M context) --- package-firewall/bash/lib/common.sh | 294 ++++++++++++++++++ package-firewall/tests/README.md | 75 +++++ package-firewall/tests/bash/harness.sh | 88 ++++++ .../tests/bash/json-primitives.sh | 191 ++++++++++++ .../tests/fixtures/.gitattributes | 5 + package-firewall/tests/fixtures/product.json | 74 +++++ package-firewall/tests/run-all.sh | 108 +++++++ 7 files changed, 835 insertions(+) create mode 100644 package-firewall/tests/README.md create mode 100644 package-firewall/tests/bash/harness.sh create mode 100755 package-firewall/tests/bash/json-primitives.sh create mode 100644 package-firewall/tests/fixtures/.gitattributes create mode 100644 package-firewall/tests/fixtures/product.json create mode 100755 package-firewall/tests/run-all.sh diff --git a/package-firewall/bash/lib/common.sh b/package-firewall/bash/lib/common.sh index 5dab948..c3ca813 100644 --- a/package-firewall/bash/lib/common.sh +++ b/package-firewall/bash/lib/common.sh @@ -22,6 +22,17 @@ # warn_if_xml_key_conflict