Skip to content

Add token registry and binary config codec for shareable links - #368

Merged
jackgranatowski merged 2 commits into
mainfrom
claude/charming-mayer-clewtf
Jun 21, 2026
Merged

Add token registry and binary config codec for shareable links#368
jackgranatowski merged 2 commits into
mainfrom
claude/charming-mayer-clewtf

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces a permanent, append-only token registry and a compact binary codec for encoding/decoding shareable configurator links. This replaces the previous name-based JSON encoding with a future-proof numeric id system, inspired by Guild Wars 2's build-template codes.

Key Changes

  • Token Registry (token-registry.json, scripts/gen-token-registry.js)

    • New append-only registry mapping design-token names to permanent 16-bit numeric ids
    • Generator script syncs with docs/api-index.json and maintains id stability
    • Removed tokens are flagged rather than deleted, preserving id space integrity
    • Contains 693 tokens with metadata tracking generation source and next available id
  • Binary Config Codec (configurator/src/lib/codec.js)

    • Compact base64url-encoded format for shareable links: (id, value) pairs instead of token names
    • Schema version 1 with forward-compatibility: unknown ids are skipped on decode, missing ids fall back to defaults
    • Self-contained module (no framework dependencies) for vendor-ability into third-party tools
    • Comprehensive test suite (configurator/tests/codec.test.js) covering round-trip encoding, malformed input tolerance, and URL safety
  • Registry Validation (scripts/check-token-registry.js)

    • CI gate ensuring id permanence: no reassignment, no reuse, no deletion
    • Verifies _meta.nextId monotonicity and that all live tokens have registry entries
    • Runs in CI pipeline to prevent accidental registry corruption
  • Integration Updates

    • configurator/src/lib/share.js: Updated to use binary codec instead of JSON
    • configurator/scripts/sync-api.mjs: Syncs registry alongside API index
    • scripts/artifacts.json: Added token-registry.json to tracked artifacts
    • package.json: Added gen-token-registry and check-token-registry scripts
    • Removed lz-string dependency from configurator (no longer needed for compression)
    • .github/workflows/ci.yml: Added registry validation gate

Implementation Details

  • Registry ids are the wire identity for config codes; token names can change without breaking old links
  • The codec is deliberately self-contained so the SLASHED WordPress plugin can vendor it verbatim
  • Empty config maps encode to empty string for uniform "nothing to share" handling
  • All tests pass with round-trip losslessness for known tokens and graceful degradation for unknown/removed ids

https://claude.ai/code/session_01GPnBf8GgSb2TxH4EFGiSjk


Summary by cubic

Introduce an append-only token registry and a compact binary codec for shareable configurator links. Links now use 16-bit token ids with base64url encoding for smaller, forward-compatible codes; CI enforces id permanence and uint16 bounds, replacing the old name-based JSON/lz-string format.

  • New Features

    • Permanent token registry token-registry.json (16-bit ids; append-only; removed tokens flagged), generated from docs/api-index.json and mirrored to configurator/src/data/token-registry.generated.json; generator refuses ids past 65535.
    • Binary config codec configurator/src/lib/codec.js: encodes (id, value) pairs, versioned, skips unknown/removed ids, drops out-of-range ids, URL-safe, and self-contained; integrated into share.js. Legacy #c=1.<lz-string> links are no longer supported (decode to defaults).
    • Tests added/updated (configurator/tests/codec.test.js, share.test.js) for round-trip, malformed input tolerance, unknown binary version rejection, uint16 bounds, and URL safety.
    • CI gate scripts/check-token-registry.js verifies id permanence, no deletions/reuse, monotonic _meta.nextId, and uint16 limits; diffs against the base branch. Workflow fetches full history (fetch-depth: 0) and runs the check; artifacts list updated.
  • Dependencies

    • Removed lz-string from the configurator.

Written for commit 5fe90ed. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jackgranatowski, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 31 minutes and 23 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b51ddb9e-9aab-420a-b6fd-e8732d9449a6

📥 Commits

Reviewing files that changed from the base of the PR and between 25508e2 and 5fe90ed.

⛔ Files ignored due to path filters (1)
  • configurator/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • .github/workflows/ci.yml
  • configurator/package.json
  • configurator/scripts/sync-api.mjs
  • configurator/src/data/token-registry.generated.json
  • configurator/src/lib/codec.js
  • configurator/src/lib/share.js
  • configurator/tests/codec.test.js
  • configurator/tests/share.test.js
  • package.json
  • scripts/artifacts.json
  • scripts/check-token-registry.js
  • scripts/gen-token-registry.js
  • token-registry.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/charming-mayer-clewtf

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…codes

Replace the lz-string share format with a compact, future-proof binary
codec modelled on Guild Wars 2 build-template codes. Each token gets a
permanent 16-bit id from a new append-only token-registry.json; a config
is encoded as a sparse (id, value) byte buffer, base64url'd into the URL
fragment (#c=). Unknown ids are skipped and missing ids fall back to
defaults, so a link minted today decodes in every later build.

- token-registry.json: canonical append-only id map, generated from
  docs/api-index.json by scripts/gen-token-registry.js (wired into
  `npm run docs`).
- scripts/check-token-registry.js + `npm run check:registry`: CI gate
  enforcing id permanence (no reassignment/deletion, monotonic nextId);
  added to the artifacts-freshness job.
- configurator/src/lib/codec.js: portable, dependency-light encode/decode
  (no Svelte/model coupling) so the WP plugin can vendor it verbatim.
- share.js: rewritten over codec.js; public surface unchanged. lz-string
  dependency dropped.
- sync-api.mjs mirrors the registry to
  src/data/token-registry.generated.json for runtime import.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPnBf8GgSb2TxH4EFGiSjk
@jackgranatowski
jackgranatowski force-pushed the claude/charming-mayer-clewtf branch from a668273 to 759b07a Compare June 21, 2026 20:55

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="configurator/src/lib/share.js">

<violation number="1" location="configurator/src/lib/share.js:60">
P2: Backward compatibility for existing share URLs was dropped. Old `#c=1.<compressed>` links will stop restoring overrides after this deploy.</violation>
</file>

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Fix all with cubic | Re-trigger cubic

Comment thread scripts/check-token-registry.js Outdated
Comment thread configurator/src/lib/codec.js Outdated
Comment thread scripts/gen-token-registry.js
// Accept a full fragment ("#c=...") or a bare payload.
const fromFragment = raw.match(/[#&]?c=([^&]+)/);
if (fromFragment) raw = fromFragment[1];
return decode(raw, registry, { sanitize: sanitizeValue, isKnown });

@cubic-dev-ai cubic-dev-ai Bot Jun 21, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Backward compatibility for existing share URLs was dropped. Old #c=1.<compressed> links will stop restoring overrides after this deploy.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At configurator/src/lib/share.js, line 60:

<comment>Backward compatibility for existing share URLs was dropped. Old `#c=1.<compressed>` links will stop restoring overrides after this deploy.</comment>

<file context>
@@ -57,39 +46,18 @@ export function encodeOverrides(map) {
+  // Accept a full fragment ("#c=...") or a bare payload.
+  const fromFragment = raw.match(/[#&]?c=([^&]+)/);
+  if (fromFragment) raw = fromFragment[1];
+  return decode(raw, registry, { sanitize: sanitizeValue, isKnown });
 }
 
</file context>
Fix with cubic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional, not a regression. This PR deliberately replaces the share format entirely: decode now understands only the new binary config code, and legacy #c=1.<lz-string> links degrade to "open with defaults" rather than restoring overrides. That was an explicit decision for the pre-1.0 framework — keeping a second lz-string decode path (and the lz-string dependency) purely for in-the-wild links wasn't worth it at this stage. The codec is forward-compatible by construction (versioned header, unknown ids skipped, missing ids fall back to defaults), so this is the last format break we expect. Leaving as-is by design.


Generated by Claude Code

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parent comment was wrong here: this PR intentionally drops legacy lz-string compatibility, and old #c=1.<compressed> links are expected to fall back to defaults. The new binary codec is the intended format, so I’ll leave this as designed.

Address code-review findings on the config-code codec:

- check-token-registry.js: diff against the base branch (GITHUB_BASE_REF /
  origin/main / main / HEAD~1) instead of HEAD. In CI the registry is already
  committed, so a HEAD baseline compared the file to itself and the
  id-permanence gate was a no-op. CI now fetches full history (fetch-depth: 0)
  so the baseline resolves. Also assert no id exceeds the uint16 wire limit.
- gen-token-registry.js: refuse to mint an id past 65535 (the 2-byte wire
  field) rather than silently aliasing tokens once the id space overflows.
- codec.js: drop registry ids outside the uint16 range in nameToId instead of
  truncating them on encode (belt-and-braces with the generator cap); covered
  by a new codec test.

The dropped backward-compat for old lz-string `#c=1.<compressed>` links is
intentional (pre-1.0, new format only — stale links degrade to defaults).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPnBf8GgSb2TxH4EFGiSjk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants