Skip to content

Feature/registry support#37

Merged
magmacomputing merged 22 commits into
mainfrom
feature/registry-support
Jun 7, 2026
Merged

Feature/registry support#37
magmacomputing merged 22 commits into
mainfrom
feature/registry-support

Conversation

@magmacomputing

@magmacomputing magmacomputing commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Breaking Changes

Ticker moved to a standalone premium plugin (separate install/registration required).
Config keys renamed: relativeTime → relativeTimeFormat; debug now accepts numeric or string levels.
UTC ISO output now uses higher-precision Temporal formatting.
New Features

New compact date/time tokens and uppercase ordinal tokens.
Duration formatting supports Intl.DurationFormat with multi-unit output.
Improvements

Centralized diagnostic/logging with numeric verbosity.
Package versions bumped to v3.0.0.
Documentation

Migration guide, release notes, and examples updated.
Tests

Legacy ticker tests removed; logging and new boundary/logger tests added.

Summary by CodeRabbit

  • Breaking Changes

    • Release upgraded to v3.0.0: Ticker extracted to a premium plugin (requires license); debug now accepts numeric levels or string labels; intl.relativeTime → intl.relativeTimeFormat; .iso yields higher‑precision Temporal output.
  • New Features

    • Built-in benchmark module; Intl.DurationFormat-based duration formatting; compact date/time and ordinal tokens; extension/plugin authoring and premium plugin scaffolding; native crypto helpers for JWS/JWT support.
  • Bug Fixes

    • Fixed registry/auth double-initialization, key-registration collisions, and ticker lifecycle issues.
  • Documentation

    • Updated migration guide, release notes, cookbook, plugin docs, and API examples.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

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

More reviews will be available in 1 minute and 16 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ 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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa75708d-aa53-48ee-b6ad-7b0658dade8a

📥 Commits

Reviewing files that changed from the base of the PR and between 55945e6 and e4d364d.

📒 Files selected for processing (3)
  • packages/tempo/src/support/support.enum.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/support/support.util.ts
📝 Walkthrough

Walkthrough

Monorepo v3 release: replace Logify with Logger/Diagnostic Engine, extract Ticker to premium, add crypto/webtoken modules, Intl/duration/token API changes, add BenchmarkModule, and migrate tests/docs/tooling to SWC and new logging contracts.

Changes

Tempo & Library v3 Cutover

Layer / File(s) Summary
Release metadata & package bumps
package.json, packages/*/package.json, CHANGELOG.md, .gitignore
Bump versions to 3.0.0, add v3 changelogs, adjust package exports/imports/scripts, and ignore local premium symlink.
Diagnostics & Logger foundation
packages/library/src/common/logger.class.ts, packages/library/src/common/boundary.library.ts, packages/library/src/common/symbol.library.ts, packages/library/src/common/coercion.library.ts
Introduce Logger, parseLogLevel, boundary.raise, asError helper, and switch symbol gating from $Logify to $LogConfig.
Library crypto & webtoken
packages/library/src/common/cipher.library.ts, packages/library/src/common/webtoken.library.ts, packages/library/src/common/buffer.library.ts, server auth usage`
Add Web Crypto-based cipher, JWS/JWT helpers, modern buffer/base64 utilities; remove legacy JWT helpers.
Tempo support & runtime refactor
packages/tempo/src/support/*, packages/tempo/src/tempo.class.ts, packages/tempo/src/tempo.type.ts
Centralize log helpers (logError/logWarn/logDebug/logTempo), add TempoError, refactor discovery/lifecycle/license wiring, adjust public types (debug → DebugLevel, relativeTime → relativeTimeFormat, licensing return shapes).
Licensing & premium scaffolding
packages/tempo/src/support/support.license.ts, packages/tempo/src/support/support.init.ts, packages/tempo/src/plugin/*, packages/tempo/package.json, rollup.config.js
Community Validator stubs, syncRevocation shape change, definePremiumPlugin/Term wrappers, premium build detection, remove core ticker mapping and add runtime throwing stub.
Duration / Intl / Formatting
packages/tempo/src/module/module.duration.ts, packages/library/src/common/international.library.ts, packages/tempo/src/module/module.format.ts, docs/tests
Wire durationFormat and Intl.DurationFormat, swap relativeTime→relativeTimeFormat, add ordinal/composite tokens and update format behavior and docs/tests.
Benchmarking & tooling
packages/tempo/src/module/module.benchmark.ts, packages/tempo/bench/*, vitest.config.ts, package vitest configs
Add BenchmarkModule, bench scripts/tests/results, migrate Vitest configs to SWC plugin, update worker settings and tsconfig paths.
Engine & parser hygiene
packages/tempo/src/engine/*, packages/tempo/src/module/*, packages/library/src/common/*
Standardize diagnostics across composer/lexer/normalizer/pattern/planner; prefer isDefined/isNumber helpers; adjust snippets/guard defaults and pattern/token templates.
Tests, docs, and examples
packages/tempo/doc/*, tests under packages/*/test/*
Update docs for v3 migration (ticker premium, debug contract), adapt tests to new logging/diagnostic APIs and option shapes, add/remove ticker tests per extraction.

Estimated code review effort
🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

"A rabbit taps the tempo key,
Logs now hum in ordered glee.
Ticker hops to premium land,
Durations dance by Intl’s hand.
Benchmarks cheer — v3 we see. 🥕"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/registry-support

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
packages/tempo/src/tempo.class.ts (2)

638-711: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Re-apply the logger level after the final config merge.

setLogLevel() runs before store/discovery/options are merged into state.config, so a debug level loaded from storage or discovery never reaches the new logger stack. After init, Tempo.config.debug can say one thing while logTempo is still running at Info.

Suggested fix
 		try {
 			setLogLevel(options.debug ?? Default?.debug ?? LOG.Info);
@@
 			this[$setConfig](state, {
 				calendar,
 				timeZone,
 				locale,
 				discovery: normalizedDiscovery,
 				formats: config.formats ?? enumify(STATE.FORMAT, false),
 				scope: 'global',
 				catch: options.catch ?? config.catch ?? false
 			},
 				{ store: storeKey, discovery: normalizedDiscovery, scope: 'global' },
 				this.readStore(storeKey),
 				this[$setDiscovery](state, rt.pluginsDb as any),
 				this[$setDiscovery](state, userDiscovery),
 				options,
 			)
+			setLogLevel(state.config.debug as any);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/tempo.class.ts` around lines 638 - 711, The logger level
is set early with setLogLevel(options.debug ?? Default?.debug ?? LOG.Info)
before this[$setConfig](...) merges store/discovery values into state.config, so
persisted or discovered debug settings are ignored; after the unified merge call
this[$setConfig](...) completes, re-apply the effective level by calling
setLogLevel with the merged value (e.g. setLogLevel(state.config.debug ??
options.debug ?? Default?.debug ?? LOG.Info) or simply
setLogLevel(state.config.debug ?? LOG.Info) so the logger reflects the final
state.config); update immediately after the this[$setConfig](...) invocation.

346-377: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Keep sandbox discovery out of the shared registries.

Tempo.create() now routes sandbox discovery through this method, but these registryUpdate(...) calls still mutate the shared registry state. A sandbox that defines formats, timeZones, numbers, or monthDay data will leak those additions back into base Tempo and other sandboxes.

Also applies to: 387-390

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/tempo.class.ts` around lines 346 - 377, The discovery
processing is mutating shared registries via registryUpdate for formats,
timeZones, numbers and MONTH_DAY; when discovery is from a sandbox this leaks
into global state. Fix by detecting sandbox discovery (e.g., a boolean flag on
the discovery object or a parameter passed into the method) and: if sandbox, do
not call registryUpdate for the entries processed in the blocks handling
discovery.timeZones, discovery.numbers, discovery.monthDay (and the formats
block) — instead merge those values into a local opts/registry object returned
or used only by the instance; if not sandbox, continue to call registryUpdate as
before. Ensure the same guard is applied for the later registryUpdate calls
related to MONTH_DAY and intl so sandbox data never mutates the shared registry.
packages/tempo/bench/bench.parse.prefilter.e2e.ts (1)

14-18: ⚠️ Potential issue | 🟡 Minor

Fix extensionless corpus path to avoid always using the fallback dataset

bench.parse.prefilter.e2e.ts reads fs.readFileSync(new URL('./bench.parse.prefilter', import.meta.url), ...), which resolves to packages/tempo/bench/bench.parse.prefilter (no extension). That extensionless file doesn’t exist in the repo (only bench.parse.prefilter.ts is present), so the benchmark will hit the fallback and produce misleading e2e numbers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/bench/bench.parse.prefilter.e2e.ts` around lines 14 - 18, The
path passed to fs.readFileSync is missing the file extension so new
URL('./bench.parse.prefilter', import.meta.url) resolves to a non-existent
extensionless file and triggers the fallback dataset; update the URL to point to
the actual file (e.g. use './bench.parse.prefilter.ts') in the call that builds
corpus so the code in bench.parse.prefilter.e2e.ts reads the real corpus file
instead of falling back.
packages/tempo/test/plugins/licensing.full.test.ts (2)

196-234: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Duplicate await statement.

Line 223 has a duplicate await rt.license.jws; that appears immediately after the same statement on line 222. This is functionally harmless (awaiting an already-resolved promise is a no-op), but it's unnecessary and may indicate a copy-paste error.

🧹 Proposed cleanup
 		const rt = getRuntime();
 		await rt.license.jws;
-		await rt.license.jws;
 		await vi.waitFor(() => expect(rt.license.status).toBe(LICENSE.Revoked));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/test/plugins/licensing.full.test.ts` around lines 196 - 234,
Remove the duplicate await call to rt.license.jws (the second await on the same
promise immediately after the first) in the test 'Eager Discovery Guard: blocks
premium plugins when license is revoked' so only a single await rt.license.jws
remains before checking rt.license.status; this cleans up the redundant no-op
await and prevents confusion about a possible copy/paste error.

101-113: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Race condition causes test failure.

The test expects LICENSE.Pending but the pipeline shows it receives 'active'. After calling Tempo.init({ license: mockToken }), the license verification may complete immediately because the mock resolves synchronously. The test should await rt.license.jws before asserting the status, or explicitly check the pre-resolution state in a deterministic way.

The pipeline error confirms this: "expected 'active' to be 'pending'".

🔧 Proposed fix

Add a guard to ensure the test checks the status before verification completes:

 test('License state is global and persists across local instances', () => {
 	const payload = { permissions: { global: {} } };
 	const mockToken = `a.${base64Encode(JSON.stringify(payload))}.c`;
 
 	Tempo.init({ license: mockToken });
+	const rt = getRuntime();
 
 	// Create a local instance
 	const local = new Tempo();
 
 	// Local instance should reflect the global license state via its runtime bridge
-	expect(Tempo.license.status).toBe(LICENSE.Pending);
+	// Note: The mock verification may complete immediately, so we check the runtime directly
+	// If you want to test Pending state, add a longer async mock or check before init completes
+	expect(rt.license.status).toMatch(/pending|active/i);
 	expect((Tempo.license as any).key).toBeUndefined();
 });

Or if you specifically need to test the Pending state, you need to prevent the mock from resolving immediately.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/test/plugins/licensing.full.test.ts` around lines 101 - 113,
The test is racy: after calling Tempo.init({ license: mockToken }) the license
verification may resolve synchronously, so assertions against
Tempo.license.status can be nondeterministic; fix by awaiting the runtime bridge
license promise before asserting (e.g. await rt.license.jws or the equivalent
promise exposed by the runtime bridge created by new Tempo()) and then assert
the resolved state, or if you intend to assert the Pending state, modify the
mock verification to delay resolution (make the verification promise
async/delayed) and then assert Tempo.license.status === LICENSE.Pending
immediately after Tempo.init; reference Tempo.init, new Tempo(), Tempo.license
and rt.license.jws to locate where to await or where to stub the verifier.
🧹 Nitpick comments (5)
packages/library/src/browser/mapper.library.ts (1)

130-131: ⚡ Quick win

Consider migrating remaining console calls to Logger for consistency.

The module now uses Logger for some logging (lines 71, 87-88), but still uses raw console.* calls at lines 130, 147, 163, 176, and 203. For a cleaner diagnostic strategy, consider migrating these remaining console calls to the log instance.

♻️ Example migration for line 130-131
-					if (opts.debug)
-						console.log('mapQuery: cache');
+					log.debug(opts, 'mapQuery: cache');

Also applies to: 147-148, 163-164, 176-177, 203-204

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/library/src/browser/mapper.library.ts` around lines 130 - 131,
Replace remaining raw console calls in
packages/library/src/browser/mapper.library.ts (inside the mapQuery flow) with
the module Logger instance (log) for consistency: change console.log('mapQuery:
cache') and the other console.* usages at the equivalent spots (the calls around
the cache path, fallback/path checks, and error/info messages—previously at
lines similar to 130,147,163,176,203) to use log.debug or
log.info/log.warn/log.error as appropriate, keeping the same message text and
honoring the existing opts.debug guard by using log.debug when opts.debug is
checked; ensure you import/use the existing log instance used on lines 71 and
87-88 and remove direct console.* usage.
packages/library/src/common/cipher.class.ts (1)

95-100: ⚡ Quick win

Non-null assertions on keypair properties assume successful generation.

The ! operators on lines 95 and 100 assume that privateKey and publicKey will always exist on the generated keypair. While this should be true for RSASSA-PKCS1-v1_5 with the specified usages, these assertions could throw if the key generation returns an unexpected structure.

🛡️ Safer alternative without assertions
 static sign = async (doc: any) =>
-  subtle.sign(keys.SignKey, (await _asymmetricKey).privateKey!, Cipher.encodeBuffer(doc))
+  subtle.sign(keys.SignKey, (await _asymmetricKey).privateKey, Cipher.encodeBuffer(doc))
     .then(result => new Uint8Array(result))
     .then(Cipher.decodeBuffer);

 static verify = async (signature: Promise<ArrayBuffer>, doc: any) =>
-  subtle.verify(keys.SignKey, (await _asymmetricKey).publicKey!, await signature, Cipher.encodeBuffer(doc));
+  subtle.verify(keys.SignKey, (await _asymmetricKey).publicKey, await signature, Cipher.encodeBuffer(doc));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/library/src/common/cipher.class.ts` around lines 95 - 100, The code
currently uses non-null assertions on (await _asymmetricKey).privateKey and
.publicKey when calling subtle.sign and subtle.verify; replace these assertions
with explicit runtime checks: await _asymmetricKey once, verify that
keypair.privateKey (for the sign flow) or keypair.publicKey (for verify) exist
and throw a descriptive error (or return a rejected Promise) if missing, then
pass the validated key to subtle.sign/subtle.verify together with
Cipher.encodeBuffer/Cipher.decodeBuffer; reference the _asymmetricKey promise,
subtle.sign/subtle.verify calls, and the Cipher.encodeBuffer/Cipher.decodeBuffer
helpers when making the change.
packages/tempo/doc/architecture.md (1)

33-33: ⚡ Quick win

Clarify the documentation phrasing for $LogConfig.

The sentence "Note that $LogConfig is already a Symbol created via Symbol.for('$LibraryLogConfig')" is somewhat awkward. Consider rephrasing for clarity.

📝 Suggested rephrasing
-- **Symbol-Gated**: Diagnostic metadata is attached via the symbol variable directly (e.g., `config[sym.$LogConfig]`), making it invisible to standard iteration (`Object.keys`) and serialization (`JSON.stringify`). Note that `$LogConfig` is already a Symbol created via `Symbol.for('$LibraryLogConfig')`.
+- **Symbol-Gated**: Diagnostic metadata is attached via `config[sym.$LogConfig]` (where `$LogConfig` is defined as `Symbol.for('$LibraryLogConfig')`), making it invisible to standard iteration (`Object.keys`) and serialization (`JSON.stringify`).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/doc/architecture.md` at line 33, Reword the awkward sentence
about $LogConfig for clarity: replace "Note that `$LogConfig` is already a
Symbol created via `Symbol.for('$LibraryLogConfig')`" with a clearer phrasing
such as "The $LogConfig identifier is a Symbol (created with
Symbol.for('$LibraryLogConfig'))" or "Note: $LogConfig is a Symbol created using
Symbol.for('$LibraryLogConfig')". Update the line referencing sym.$LogConfig and
Symbol.for('$LibraryLogConfig') in the architecture.md paragraph so it reads
smoothly and unambiguously.
packages/library/src/common/logger.class.ts (1)

96-96: 💤 Low value

Consider the semantic difference between trace and debug console methods.

Mapping Method.Trace to console.debug (line 96) works functionally, but console.trace() is a standard method that prints the call stack. Users might expect .trace() to produce stack traces rather than debug-level output. If stack traces are not needed, consider renaming the method or documenting this design choice more explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/library/src/common/logger.class.ts` at line 96, The current mapping
maps Method.Trace to console.debug which hides the semantic behavior of
console.trace; update the mapping in logger.class (the assignment that sets
consoleMethod for Method.Trace) to use 'trace' so calls to Method.Trace invoke
console.trace and produce a stack trace, or if stack traces are intentionally
undesired, rename the enum value Method.Trace to Method.Debug (and update all
callers) and add a clear comment in logger.class explaining the chosen behavior.
packages/tempo/test/module/module.benchmark.test.ts (1)

23-23: ⚡ Quick win

Use a more robust assertion for success rate.

The exact string match toBe('50.0%') is fragile and will break if formatting changes (e.g., to '50%' or '50.00%'). Consider using a regex or checking the numeric value instead.

♻️ Proposed fix
-		expect(native.successRate).toBe('50.0%');
+		expect(native.successRate).toMatch(/50(\.0)?%/);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/test/module/module.benchmark.test.ts` at line 23, Replace the
fragile exact string assertion for native.successRate in the test
(module.benchmark.test.ts) with a tolerant check: either parse the numeric
percentage from native.successRate and assert the numeric value equals 50 (or
within a small delta), or assert the string matches a regex like /^50(\.0+)?%$/;
update the expectation that currently uses
expect(native.successRate).toBe('50.0%') to one of these more robust forms to
avoid formatting brittleness.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Line 8: Update the release date in the CHANGELOG.md entry header "## [3.0.0] -
2026-06-01" to the correct publication date (e.g., change "2026-06-01" to
"2026-06-05" or the intended date) so the release heading accurately reflects
the actual release/PR date.

In `@packages/library/src/common/boundary.library.ts`:
- Line 32: Replace the call that logs only error.message with a call that passes
the full Error object to the logger (i.e., use context.logger.error with the
Error instance rather than error.message) so the stack and metadata are
preserved; update any surrounding error handling in the function where
context.logger.error is called to accept an Error object if necessary (refer to
the symbol context.logger.error in boundary.library.ts).

In `@packages/library/src/common/cipher.class.ts`:
- Around line 16-22: The module-level promises _cryptoKey and _asymmetricKey are
created without error handling which can cause unhandled rejections before first
use; update the initialization to handle failures by creating a safe init
routine (e.g., an async initKeys or lazy factory) that wraps subtle.generateKey
calls in try/catch (or attaches .catch) and stores either the resolved
CryptoKey/CryptoKeyPair or a captured error; then have Cipher.encrypt,
Cipher.decrypt, Cipher.sign and Cipher.verify await the initialized result and
rethrow the captured error with a clear message if key generation failed so
errors surface deterministically instead of producing unhandled rejections.

In `@packages/library/src/common/international.library.ts`:
- Around line 24-27: getDF currently constructs new (Intl as
any).DurationFormat(...) with no protection; wrap that construction in a
try/catch and return a safe fallback object when construction throws or returns
a partial implementation. Specifically, inside getDF (the memoized factory) try
to construct (Intl as any).DurationFormat(locale, options) and verify it has a
callable format method; on any error or missing format, return an object with
format: (duration) => String(duration) (or a sensible fallback string) so
callers like formatDuration can safely call .format without crashing.

In `@packages/library/src/common/logger.class.ts`:
- Around line 32-36: parseLogLevel currently accepts any numeric DebugLevel and
returns it as LOG without bounds checking; update the isNumber branch in
parseLogLevel to validate that the numeric value is within the valid LOG enum
range (e.g., 0–5) and return fallback if it's out of range (or clamp to the
nearest valid value), so invalid numbers like 999 won't be treated as a valid
LOG; reference the parseLogLevel function and the LOG enum (and use Level/Method
branches unchanged) when adding this numeric validation.

In `@packages/library/test/common/boundary.library.test.ts`:
- Line 23: Update the test assertion in boundary.library.test.ts so it expects
an Error object instead of the literal message string: change the assertion
referencing mockLogger.error to verify that mockLogger.error was called with an
Error instance (or with a new Error('Test Exception')) so it matches the
implementation that passes the full Error object.

In `@packages/tempo/bench/benchmark-results.json`:
- Around line 1-42: The committed autogenerated benchmark file is causing churn;
update the test runner that calls fs.writeFileSync('benchmark-results.json',
...) (in runner.test.ts) to write outputs to an untracked path (e.g., a tmp or
bench-output directory) or to a timestamped/versioned filename, and add a
.gitignore rule to ignore bench JSON outputs (e.g., ignore
benchmark-results.json or *.bench/*.json or packages/tempo/bench/*.json) so
CI/local runs don’t change tracked files; alternatively, if you intend to keep a
snapshot, make the runner produce explicit snapshot files and document that
behavior in tempo.benchmarks.md.

In `@packages/tempo/bin/push-docs.sh`:
- Line 36: Quote the branch variable when invoking git to avoid word-splitting
or special-character issues: replace uses of git checkout $CURRENT_BRANCH with
git checkout "$CURRENT_BRANCH" (apply at the other occurrence as well) — locate
the git checkout calls that reference the CURRENT_BRANCH variable and wrap the
variable in double quotes.
- Line 30: Update the git checkout invocation in push-docs.sh to quote the
branch variable but leave the paths unquoted: ensure the CURRENT_BRANCH
reference is quoted (to prevent globbing/word-splitting) while DOC_PATHS remains
unquoted so it can expand to multiple arguments; modify the line using git
checkout with "$CURRENT_BRANCH" -- $DOC_PATHS to fix the issue in the script.

In `@packages/tempo/src/support/support.init.ts`:
- Around line 167-174: The current assignment to runtime.license.status can end
up as null/undefined when res.status is unexpected; update the logic that builds
desc and uses statusMap so the final value always falls back to LICENSE.Invalid
(use LICENSE.Invalid instead of res.status when no mapping found). Specifically,
ensure desc handles null/undefined safely (so desc is not the string
'null'/'undefined') and change the lookup to use statusMap[desc] ??
LICENSE.Invalid; update references in this block (desc, statusMap,
runtime.license.status, LICENSE.Invalid) accordingly.

In `@packages/tempo/src/support/support.license.ts`:
- Around line 29-37: definePremiumPlugin currently only replaces object hook
properties but leaves function-style plugins (passed to Tempo.extend) untouched;
detect when the provided plugin is a function (typeof plugin === 'function') and
replace it with a wrapper function that immediately throws the same license
Error (use the existing throwLicense message) so function plugins cannot execute
in community builds, while keeping the existing behavior for object plugins
(replace install/define/resolve). Keep the logWarn and return type semantics
(return the replaced wrapper or modified object) and ensure references to
definePremiumPlugin and Tempo.extend behavior are considered.

In `@packages/tempo/src/support/support.util.ts`:
- Around line 52-56: The code duplicates appended text because when err is a
string the branch using isString(err) builds new Error(`${err} ${text}`) and
then the subsequent isError/isString check appends text again; fix by making the
isString(err) branch create new Error(err) (omit `${text}`) and let the existing
block that checks isError(err) and appends text handle adding concatMsg(msg), or
alternatively add a guard so the second append only runs when the original err
was not a string; update the logic around concatMsg(msg), isString(err),
isError(err) and err.message accordingly.

In `@packages/tempo/src/tsconfig.repl.json`:
- Around line 29-32: The tsconfig REPL path mapping for the alias
"`#tempo/license`" contains a dead first target "../premium/src/index.ts" which
does not exist in the repo and is always bypassed in favor of
"./support/support.license.ts"; remove the non-existent
"../premium/src/index.ts" entry from the "`#tempo/license`" array, or if it is
intentionally scaffolding add a one-line comment/TODO next to the alias
explaining that the top-level premium package will be added later so reviewers
know it’s intentional, keeping the alias array only with the valid
"./support/support.license.ts" entry otherwise.

In `@packages/tempo/test/module/module.benchmark.test.ts`:
- Line 35: Remove the leftover debug console.log call that prints the benchmark
results: locate the console.log('BENCHMARK RESULTS:', results) in the
module.benchmark.test.ts test and delete it (or replace it with an appropriate
assertion or test-runner logger if you need to persist output), ensuring only
test assertions remain and no debug stdout is emitted during CI runs.

---

Outside diff comments:
In `@packages/tempo/bench/bench.parse.prefilter.e2e.ts`:
- Around line 14-18: The path passed to fs.readFileSync is missing the file
extension so new URL('./bench.parse.prefilter', import.meta.url) resolves to a
non-existent extensionless file and triggers the fallback dataset; update the
URL to point to the actual file (e.g. use './bench.parse.prefilter.ts') in the
call that builds corpus so the code in bench.parse.prefilter.e2e.ts reads the
real corpus file instead of falling back.

In `@packages/tempo/src/tempo.class.ts`:
- Around line 638-711: The logger level is set early with
setLogLevel(options.debug ?? Default?.debug ?? LOG.Info) before
this[$setConfig](...) merges store/discovery values into state.config, so
persisted or discovered debug settings are ignored; after the unified merge call
this[$setConfig](...) completes, re-apply the effective level by calling
setLogLevel with the merged value (e.g. setLogLevel(state.config.debug ??
options.debug ?? Default?.debug ?? LOG.Info) or simply
setLogLevel(state.config.debug ?? LOG.Info) so the logger reflects the final
state.config); update immediately after the this[$setConfig](...) invocation.
- Around line 346-377: The discovery processing is mutating shared registries
via registryUpdate for formats, timeZones, numbers and MONTH_DAY; when discovery
is from a sandbox this leaks into global state. Fix by detecting sandbox
discovery (e.g., a boolean flag on the discovery object or a parameter passed
into the method) and: if sandbox, do not call registryUpdate for the entries
processed in the blocks handling discovery.timeZones, discovery.numbers,
discovery.monthDay (and the formats block) — instead merge those values into a
local opts/registry object returned or used only by the instance; if not
sandbox, continue to call registryUpdate as before. Ensure the same guard is
applied for the later registryUpdate calls related to MONTH_DAY and intl so
sandbox data never mutates the shared registry.

In `@packages/tempo/test/plugins/licensing.full.test.ts`:
- Around line 196-234: Remove the duplicate await call to rt.license.jws (the
second await on the same promise immediately after the first) in the test 'Eager
Discovery Guard: blocks premium plugins when license is revoked' so only a
single await rt.license.jws remains before checking rt.license.status; this
cleans up the redundant no-op await and prevents confusion about a possible
copy/paste error.
- Around line 101-113: The test is racy: after calling Tempo.init({ license:
mockToken }) the license verification may resolve synchronously, so assertions
against Tempo.license.status can be nondeterministic; fix by awaiting the
runtime bridge license promise before asserting (e.g. await rt.license.jws or
the equivalent promise exposed by the runtime bridge created by new Tempo()) and
then assert the resolved state, or if you intend to assert the Pending state,
modify the mock verification to delay resolution (make the verification promise
async/delayed) and then assert Tempo.license.status === LICENSE.Pending
immediately after Tempo.init; reference Tempo.init, new Tempo(), Tempo.license
and rt.license.jws to locate where to await or where to stub the verifier.

---

Nitpick comments:
In `@packages/library/src/browser/mapper.library.ts`:
- Around line 130-131: Replace remaining raw console calls in
packages/library/src/browser/mapper.library.ts (inside the mapQuery flow) with
the module Logger instance (log) for consistency: change console.log('mapQuery:
cache') and the other console.* usages at the equivalent spots (the calls around
the cache path, fallback/path checks, and error/info messages—previously at
lines similar to 130,147,163,176,203) to use log.debug or
log.info/log.warn/log.error as appropriate, keeping the same message text and
honoring the existing opts.debug guard by using log.debug when opts.debug is
checked; ensure you import/use the existing log instance used on lines 71 and
87-88 and remove direct console.* usage.

In `@packages/library/src/common/cipher.class.ts`:
- Around line 95-100: The code currently uses non-null assertions on (await
_asymmetricKey).privateKey and .publicKey when calling subtle.sign and
subtle.verify; replace these assertions with explicit runtime checks: await
_asymmetricKey once, verify that keypair.privateKey (for the sign flow) or
keypair.publicKey (for verify) exist and throw a descriptive error (or return a
rejected Promise) if missing, then pass the validated key to
subtle.sign/subtle.verify together with Cipher.encodeBuffer/Cipher.decodeBuffer;
reference the _asymmetricKey promise, subtle.sign/subtle.verify calls, and the
Cipher.encodeBuffer/Cipher.decodeBuffer helpers when making the change.

In `@packages/library/src/common/logger.class.ts`:
- Line 96: The current mapping maps Method.Trace to console.debug which hides
the semantic behavior of console.trace; update the mapping in logger.class (the
assignment that sets consoleMethod for Method.Trace) to use 'trace' so calls to
Method.Trace invoke console.trace and produce a stack trace, or if stack traces
are intentionally undesired, rename the enum value Method.Trace to Method.Debug
(and update all callers) and add a clear comment in logger.class explaining the
chosen behavior.

In `@packages/tempo/doc/architecture.md`:
- Line 33: Reword the awkward sentence about $LogConfig for clarity: replace
"Note that `$LogConfig` is already a Symbol created via
`Symbol.for('$LibraryLogConfig')`" with a clearer phrasing such as "The
$LogConfig identifier is a Symbol (created with
Symbol.for('$LibraryLogConfig'))" or "Note: $LogConfig is a Symbol created using
Symbol.for('$LibraryLogConfig')". Update the line referencing sym.$LogConfig and
Symbol.for('$LibraryLogConfig') in the architecture.md paragraph so it reads
smoothly and unambiguously.

In `@packages/tempo/test/module/module.benchmark.test.ts`:
- Line 23: Replace the fragile exact string assertion for native.successRate in
the test (module.benchmark.test.ts) with a tolerant check: either parse the
numeric percentage from native.successRate and assert the numeric value equals
50 (or within a small delta), or assert the string matches a regex like
/^50(\.0+)?%$/; update the expectation that currently uses
expect(native.successRate).toBe('50.0%') to one of these more robust forms to
avoid formatting brittleness.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 26169a30-33b5-46a4-89d9-a46d8e23a663

📥 Commits

Reviewing files that changed from the base of the PR and between 5eed3a3 and bd7ddc0.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (128)
  • .gitignore
  • CHANGELOG.md
  • package.json
  • packages/library/doc/browser/types.md
  • packages/library/package.json
  • packages/library/src/browser/mapper.library.ts
  • packages/library/src/browser/webstore.class.ts
  • packages/library/src/common.index.ts
  • packages/library/src/common/array.library.ts
  • packages/library/src/common/assertion.library.ts
  • packages/library/src/common/boundary.library.ts
  • packages/library/src/common/cipher.class.ts
  • packages/library/src/common/class.library.ts
  • packages/library/src/common/function.library.ts
  • packages/library/src/common/international.library.ts
  • packages/library/src/common/logger.class.ts
  • packages/library/src/common/logify.class.ts
  • packages/library/src/common/number.library.ts
  • packages/library/src/common/object.library.ts
  • packages/library/src/common/pledge.class.ts
  • packages/library/src/common/reflection.library.ts
  • packages/library/src/common/symbol.library.ts
  • packages/library/src/common/type.library.ts
  • packages/library/src/server/file.library.ts
  • packages/library/test/common/boundary.library.test.ts
  • packages/library/test/common/logger.class.test.ts
  • packages/library/test/common/logify.class.test.ts
  • packages/library/test/common/pledge.class.test.ts
  • packages/library/vitest.config.ts
  • packages/tempo/.vitepress/config.ts
  • packages/tempo/CHANGELOG.md
  • packages/tempo/CONTRIBUTING.md
  • packages/tempo/bench/bench.parse.prefilter.e2e.ts
  • packages/tempo/bench/bench.parse.prefilter.ts
  • packages/tempo/bench/benchmark-results.json
  • packages/tempo/bench/runner.test.ts
  • packages/tempo/bench/test-benchmark-output.ts
  • packages/tempo/bench/test-pizza.test.ts
  • packages/tempo/bench/test-pizza.ts
  • packages/tempo/bench/tsconfig.json
  • packages/tempo/bin/push-docs.sh
  • packages/tempo/bin/repl.ts
  • packages/tempo/bin/tsconfig.json
  • packages/tempo/doc/architecture.md
  • packages/tempo/doc/commercial.md
  • packages/tempo/doc/migration-guide.md
  • packages/tempo/doc/release-notes-v3.0.0.md
  • packages/tempo/doc/releases/v2.x.md
  • packages/tempo/doc/sandbox-factory.md
  • packages/tempo/doc/soft_freeze_strategy.md
  • packages/tempo/doc/tempo.benchmarks.md
  • packages/tempo/doc/tempo.config.md
  • packages/tempo/doc/tempo.cookbook.md
  • packages/tempo/doc/tempo.debugging.md
  • packages/tempo/doc/tempo.duration.md
  • packages/tempo/doc/tempo.extension.md
  • packages/tempo/doc/tempo.format.md
  • packages/tempo/doc/tempo.layout.md
  • packages/tempo/doc/tempo.month-day.md
  • packages/tempo/doc/tempo.pledge.md
  • packages/tempo/doc/tempo.plugin.md
  • packages/tempo/doc/tempo.term.md
  • packages/tempo/doc/tempo.ticker.md
  • packages/tempo/importmap.json
  • packages/tempo/index.md
  • packages/tempo/package.json
  • packages/tempo/rollup.config.js
  • packages/tempo/src/engine/engine.alias.ts
  • packages/tempo/src/engine/engine.composer.ts
  • packages/tempo/src/engine/engine.guard.ts
  • packages/tempo/src/engine/engine.lexer.ts
  • packages/tempo/src/engine/engine.normalizer.ts
  • packages/tempo/src/engine/engine.pattern.ts
  • packages/tempo/src/engine/engine.planner.ts
  • packages/tempo/src/engine/engine.term.ts
  • packages/tempo/src/library.index.ts
  • packages/tempo/src/module/module.benchmark.ts
  • packages/tempo/src/module/module.duration.ts
  • packages/tempo/src/module/module.format.ts
  • packages/tempo/src/module/module.mutate.ts
  • packages/tempo/src/module/module.parse.ts
  • packages/tempo/src/plugin/plugin.index.ts
  • packages/tempo/src/plugin/plugin.util.ts
  • packages/tempo/src/support/support.default.ts
  • packages/tempo/src/support/support.enum.ts
  • packages/tempo/src/support/support.error.ts
  • packages/tempo/src/support/support.index.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/support/support.intl.ts
  • packages/tempo/src/support/support.license.ts
  • packages/tempo/src/support/support.register.ts
  • packages/tempo/src/support/support.symbol.ts
  • packages/tempo/src/support/support.util.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.type.ts
  • packages/tempo/src/tsconfig.json
  • packages/tempo/src/tsconfig.repl.json
  • packages/tempo/test/core/alias-engine-protochain.test.ts
  • packages/tempo/test/core/alias-engine.test.ts
  • packages/tempo/test/core/dispose.core.test.ts
  • packages/tempo/test/core/sandbox-factory.test.ts
  • packages/tempo/test/engine/parse.prefilter.flag.test.ts
  • packages/tempo/test/instance/instance.since.rtf.test.ts
  • packages/tempo/test/issues/issue-fixes.test.ts
  • packages/tempo/test/module/module.benchmark.test.ts
  • packages/tempo/test/plugins/duration.balance.test.ts
  • packages/tempo/test/plugins/licensing.full.test.ts
  • packages/tempo/test/plugins/plugin_registration.test.ts
  • packages/tempo/test/plugins/slick.verification.test.ts
  • packages/tempo/test/plugins/ticker.active.test.ts
  • packages/tempo/test/plugins/ticker.hang.test.ts
  • packages/tempo/test/plugins/ticker.options.test.ts
  • packages/tempo/test/plugins/ticker.patterns.test.ts
  • packages/tempo/test/plugins/ticker.pulse.test.ts
  • packages/tempo/test/plugins/ticker.stop.test.ts
  • packages/tempo/test/plugins/ticker.term.core.test.ts
  • packages/tempo/test/plugins/ticker_cold_start.test.ts
  • packages/tempo/test/support/error-handling.test.ts
  • packages/tempo/test/support/library-import.test.ts
  • packages/tempo/test/support/proof.test.ts
  • packages/tempo/test/support/symbol-import.test.ts
  • packages/tempo/test/tsconfig.json
  • packages/tempo/tsconfig.build.json
  • packages/tempo/tsconfig.json
  • packages/tempo/vitest.config.ts
  • packages/tempo/vitest.workspace.ts
  • vitest.config.ts
  • vitest.workspace.ts
💤 Files with no reviewable changes (18)
  • packages/tempo/test/plugins/ticker.pulse.test.ts
  • vitest.workspace.ts
  • packages/tempo/vitest.workspace.ts
  • packages/tempo/test/plugins/ticker.hang.test.ts
  • packages/tempo/test/plugins/ticker_cold_start.test.ts
  • packages/tempo/test/support/error-handling.test.ts
  • packages/tempo/test/support/library-import.test.ts
  • packages/tempo/test/tsconfig.json
  • packages/tempo/test/plugins/ticker.stop.test.ts
  • packages/tempo/test/plugins/ticker.options.test.ts
  • packages/library/test/common/logify.class.test.ts
  • packages/tempo/importmap.json
  • packages/library/src/common/logify.class.ts
  • packages/tempo/bin/tsconfig.json
  • packages/tempo/test/plugins/ticker.term.core.test.ts
  • packages/tempo/test/plugins/ticker.patterns.test.ts
  • packages/tempo/test/plugins/ticker.active.test.ts
  • packages/tempo/test/plugins/slick.verification.test.ts

Comment thread CHANGELOG.md Outdated
Comment thread packages/library/src/common/boundary.library.ts Outdated
Comment thread packages/library/src/common/cipher.class.ts Outdated
Comment thread packages/library/src/common/international.library.ts
Comment thread packages/library/src/common/logger.class.ts
Comment thread packages/tempo/src/support/support.license.ts
Comment thread packages/tempo/src/support/support.util.ts Outdated
Comment thread packages/tempo/src/tempo.class.ts
Comment thread packages/tempo/src/tsconfig.repl.json
Comment thread packages/tempo/test/module/module.benchmark.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/tempo/bin/push-docs.sh (1)

7-7: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use an array for doc paths to avoid path-splitting bugs.

Line 7 + Line 30 rely on word-splitting. If the repo path contains spaces, checkout arguments break. Use a Bash array and expand with "${DOC_PATHS[@]}".

Proposed fix
-DOC_PATHS="$TEMPO_ROOT/doc/ $TEMPO_ROOT/img/ $TEMPO_ROOT/index.md $TEMPO_ROOT/typedoc.json $TEMPO_ROOT/.vitepress/"
+DOC_PATHS=(
+  "$TEMPO_ROOT/doc/"
+  "$TEMPO_ROOT/img/"
+  "$TEMPO_ROOT/index.md"
+  "$TEMPO_ROOT/typedoc.json"
+  "$TEMPO_ROOT/.vitepress/"
+)
@@
-git checkout "$CURRENT_BRANCH" -- $DOC_PATHS
+git checkout "$CURRENT_BRANCH" -- "${DOC_PATHS[@]}"

Also applies to: 30-30

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/bin/push-docs.sh` at line 7, Replace the space-delimited
DOC_PATHS string with a Bash array named DOC_PATHS (e.g., DOC_PATHS=( ... )) and
update any usage sites (the checkout/rsync/git commands referencing DOC_PATHS,
noted around the current startLine 30) to expand the paths as "${DOC_PATHS[@]}",
so paths containing spaces are preserved; ensure quotes are used when expanding
and that any loops or commands that previously relied on word-splitting now
iterate over the array elements.

Source: Linters/SAST tools

♻️ Duplicate comments (1)
packages/tempo/src/support/support.init.ts (1)

166-173: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Unexpected status values may bypass LICENSE.Invalid fallback.

The fallback chain statusMap[desc] ?? res.status ?? LICENSE.Invalid allows unexpected status values (like 'pending' or other strings) to pass through as res.status instead of defaulting to LICENSE.Invalid. This contradicts the intent of the statusMap normalization.

🛡️ Suggested fix to ensure strict mapping
-runtime.license.status = statusMap[desc] ?? res.status ?? LICENSE.Invalid;
+runtime.license.status = statusMap[desc] ?? LICENSE.Invalid;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/support/support.init.ts` around lines 166 - 173, The code
lets unexpected res.status values bypass normalization because it falls back to
res.status; change the assignment so only mapped values are accepted and
anything else becomes LICENSE.Invalid. Specifically, update the logic around
desc, statusMap, and runtime.license.status (currently using statusMap[desc] ??
res.status ?? LICENSE.Invalid) to use only statusMap[desc] ?? LICENSE.Invalid,
ensuring runtime.license.status is set to a member of LICENSE or LICENSE.Invalid
for unrecognized statuses.
🧹 Nitpick comments (2)
packages/tempo/src/support/support.init.ts (1)

185-193: 💤 Low value

Silent catch in revocationPromise handler.

The .catch(() => { /* silent fail-safe */ }) swallows all errors including unexpected runtime exceptions. While this prevents unhandled rejections, consider logging at debug/trace level for diagnostics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/support/support.init.ts` around lines 185 - 193, The catch
block on the revocationPromise silently swallows errors; update the handler for
res.revocationPromise in support.init.ts to log caught errors (at debug/trace
level) instead of leaving the catch empty — preserve the fail-safe behavior but
call an existing logger (e.g., logDebug or logTrace) with the error and context
(include initialJti, initialKey, and runtime.license.jti/key) so you still set
runtime.license.status = LICENSE.Revoked and runtime.license.error when
appropriate; reference the res.revocationPromise.then(...) chain,
runtime.license, LICENSE.Revoked, logWarn, and state.config to locate where to
add the debug-level logging in the .catch.
packages/tempo/src/support/support.license.ts (1)

15-24: 💤 Low value

Unused claims variable in community Validator.verify().

The decodeJWT(this.key) result is assigned to claims but never used. This appears intentional for the no-op community build, but the unused variable could be removed for clarity.

🧹 Remove unused variable
 async verify() {
   // Decodes but DOES NOT verify the signature. 
   // Cannot safely unlock Premium Plugins without cryptographic proof.
-  const claims = decodeJWT(this.key);
+  decodeJWT(this.key); // No-op: decodes but cannot verify without crypto engine
   return {
     status: 'invalid' as const,
     scopes: {},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/support/support.license.ts` around lines 15 - 24, The
verify() method assigns decodeJWT(this.key) to an unused variable claims; remove
the unused variable by either deleting the call entirely if there are no
side-effects, or invoking decodeJWT(this.key) without assignment (i.e., call it
for side-effects only) inside the async verify() method. Update the function
body in support.license.ts (the async verify() method) to eliminate the unused
claims variable while keeping behavior consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/library/src/common/buffer.library.ts`:
- Around line 14-15: The code directly references the global identifier Buffer
inside isDefined(Buffer), which throws a ReferenceError in environments without
Buffer; replace those checks with a safe existence test like typeof Buffer !==
'undefined' or using globalThis?.Buffer before calling
Buffer.from(...).toString('base64') (apply the same change where Buffer is
checked/used at the other location), so the btoa/atob fallback is reachable
without errors.

In `@packages/library/src/common/cipher.library.ts`:
- Around line 56-61: encrypt accepts any but passes data to encodeBuffer which
only handles strings, causing silent corruption for non-strings; update the
encrypt function (encrypt) to either restrict its input type to string or
explicitly serialize non-string inputs (e.g., JSON.stringify) before calling
encodeBuffer(data), and ensure callers reflect the chosen contract; locate
references to encodeBuffer and _cryptoKey in encrypt to implement the change and
add a short validation/serialization step so only valid string bytes are
encrypted.
- Around line 83-91: The sign function currently decodes signature bytes to
UTF‑8 via decodeBuffer causing lossy signatures and mismatch with verify; update
sign (and ensure verify) to return and accept raw binary (ArrayBuffer or
Uint8Array) directly from subtle.sign/subtle.verify without calling decodeBuffer
so the signature remains reversible (refer to sign, verify, decodeBuffer,
_asymmetricKey, subtle.sign, subtle.verify); also fix encrypt to either enforce
a string input or explicitly serialize/coerce non-string data (e.g.
JSON.stringify) before passing to encodeBuffer to avoid silent corruption (refer
to encrypt and encodeBuffer) so encoding is deterministic and lossless.

In `@packages/library/src/common/webtoken.library.ts`:
- Around line 13-23: The decodeJWT function currently uses atob(...) or
Buffer.from(...).toString() which yields raw binary strings and corrupts
non-ASCII UTF‑8 JSON payloads; change decodeJWT to convert the base64url payload
into a Buffer via the shared helper base64ToBuffer and then decode the UTF‑8
bytes using decodeBuffer before JSON.parse (use base64url→base64 normalization
first). Also update verifyJWS to ensure you add proper '=' padding when
converting base64url to base64 before calling base64ToBuffer (so the atob
fallback gets correctly padded input), keeping the existing normalization logic
but appending padding as needed.

---

Outside diff comments:
In `@packages/tempo/bin/push-docs.sh`:
- Line 7: Replace the space-delimited DOC_PATHS string with a Bash array named
DOC_PATHS (e.g., DOC_PATHS=( ... )) and update any usage sites (the
checkout/rsync/git commands referencing DOC_PATHS, noted around the current
startLine 30) to expand the paths as "${DOC_PATHS[@]}", so paths containing
spaces are preserved; ensure quotes are used when expanding and that any loops
or commands that previously relied on word-splitting now iterate over the array
elements.

---

Duplicate comments:
In `@packages/tempo/src/support/support.init.ts`:
- Around line 166-173: The code lets unexpected res.status values bypass
normalization because it falls back to res.status; change the assignment so only
mapped values are accepted and anything else becomes LICENSE.Invalid.
Specifically, update the logic around desc, statusMap, and
runtime.license.status (currently using statusMap[desc] ?? res.status ??
LICENSE.Invalid) to use only statusMap[desc] ?? LICENSE.Invalid, ensuring
runtime.license.status is set to a member of LICENSE or LICENSE.Invalid for
unrecognized statuses.

---

Nitpick comments:
In `@packages/tempo/src/support/support.init.ts`:
- Around line 185-193: The catch block on the revocationPromise silently
swallows errors; update the handler for res.revocationPromise in support.init.ts
to log caught errors (at debug/trace level) instead of leaving the catch empty —
preserve the fail-safe behavior but call an existing logger (e.g., logDebug or
logTrace) with the error and context (include initialJti, initialKey, and
runtime.license.jti/key) so you still set runtime.license.status =
LICENSE.Revoked and runtime.license.error when appropriate; reference the
res.revocationPromise.then(...) chain, runtime.license, LICENSE.Revoked,
logWarn, and state.config to locate where to add the debug-level logging in the
.catch.

In `@packages/tempo/src/support/support.license.ts`:
- Around line 15-24: The verify() method assigns decodeJWT(this.key) to an
unused variable claims; remove the unused variable by either deleting the call
entirely if there are no side-effects, or invoking decodeJWT(this.key) without
assignment (i.e., call it for side-effects only) inside the async verify()
method. Update the function body in support.license.ts (the async verify()
method) to eliminate the unused claims variable while keeping behavior
consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cd99dddf-6db5-43f2-95c8-4c66fcd674cb

📥 Commits

Reviewing files that changed from the base of the PR and between bd7ddc0 and f2738ba.

📒 Files selected for processing (42)
  • .gitignore
  • CHANGELOG.md
  • packages/library/CHANGELOG.md
  • packages/library/src/browser/mapper.library.ts
  • packages/library/src/common.index.ts
  • packages/library/src/common/boundary.library.ts
  • packages/library/src/common/buffer.library.ts
  • packages/library/src/common/cipher.class.ts
  • packages/library/src/common/cipher.library.ts
  • packages/library/src/common/coercion.library.ts
  • packages/library/src/common/international.library.ts
  • packages/library/src/common/logger.class.ts
  • packages/library/src/common/utility.library.ts
  • packages/library/src/common/webtoken.library.ts
  • packages/library/src/server.index.ts
  • packages/library/src/server/auth.library.ts
  • packages/library/src/server/buffer.library.ts
  • packages/library/test/common/boundary.library.test.ts
  • packages/tempo/CHANGELOG.md
  • packages/tempo/bench/bench.parse.prefilter.e2e.ts
  • packages/tempo/bin/push-docs.sh
  • packages/tempo/doc/architecture.md
  • packages/tempo/doc/migration-guide.md
  • packages/tempo/doc/sandbox-factory.md
  • packages/tempo/doc/tempo.config.md
  • packages/tempo/doc/tempo.debugging.md
  • packages/tempo/package.json
  • packages/tempo/src/engine/engine.composer.ts
  • packages/tempo/src/engine/engine.lexer.ts
  • packages/tempo/src/engine/engine.normalizer.ts
  • packages/tempo/src/library.index.ts
  • packages/tempo/src/module/module.parse.ts
  • packages/tempo/src/plugin/extend/extend.ticker.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/support/support.license.ts
  • packages/tempo/src/support/support.runtime.ts
  • packages/tempo/src/support/support.util.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.type.ts
  • packages/tempo/src/tsconfig.repl.json
  • packages/tempo/test/module/module.benchmark.test.ts
  • packages/tempo/test/plugins/licensing.full.test.ts
💤 Files with no reviewable changes (4)
  • packages/tempo/src/tsconfig.repl.json
  • packages/library/src/server/buffer.library.ts
  • packages/library/src/server.index.ts
  • packages/library/src/common/cipher.class.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/library/CHANGELOG.md
  • packages/tempo/doc/architecture.md
  • CHANGELOG.md
  • packages/tempo/doc/tempo.debugging.md
  • packages/tempo/doc/migration-guide.md
  • packages/tempo/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/tempo/doc/sandbox-factory.md
  • packages/library/test/common/boundary.library.test.ts
  • packages/library/src/common.index.ts
  • packages/library/src/common/boundary.library.ts
  • packages/tempo/src/engine/engine.normalizer.ts
  • .gitignore
  • packages/tempo/test/module/module.benchmark.test.ts
  • packages/library/src/common/logger.class.ts
  • packages/tempo/doc/tempo.config.md
  • packages/tempo/src/engine/engine.composer.ts
  • packages/tempo/src/support/support.util.ts

Comment thread packages/library/src/common/buffer.library.ts Outdated
Comment thread packages/library/src/common/cipher.library.ts
Comment thread packages/library/src/common/cipher.library.ts
Comment thread packages/library/src/common/webtoken.library.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/tempo/src/support/support.init.ts`:
- Around line 166-167: The code assigns verifier output directly to
runtime.license.status and runtime.license.scopes; validate both before
applying: check res.status against the allowed LICENSE enum members (accept only
known values like LICENSE.Valid / LICENSE.Invalid / LICENSE.Blocked, otherwise
set runtime.license.status = LICENSE.Invalid) and ensure res.scopes is an
object/expected shape (if typeof res.scopes !== 'object' || res.scopes === null
use an empty object or the existing runtime.license.scopes fallback). Update the
assignment site (where runtime.license.status and runtime.license.scopes are
set) to perform these guards so unexpected values cannot bypass blocked-status
checks or poison downstream state.

In `@packages/tempo/src/support/support.util.ts`:
- Around line 221-223: The function resolveDisplayStatus currently maps any
unrecognized status to LICENSE.Active; change it so unknown inputs are mapped to
a safe "unknown" value instead of Active: update resolveDisplayStatus to check
String(status) against LICENSE.values() and return that value if present,
otherwise return LICENSE.Unknown (or a dedicated safe constant on the LICENSE
enum/object) so unexpected statuses do not present as Active; ensure references
to LICENSE.values() and LICENSE.Unknown are used consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 091100ba-d369-4d3c-8984-f97805d24d3b

📥 Commits

Reviewing files that changed from the base of the PR and between f2738ba and 55945e6.

📒 Files selected for processing (13)
  • packages/library/src/common/buffer.library.ts
  • packages/library/src/common/cipher.library.ts
  • packages/library/src/common/coercion.library.ts
  • packages/library/src/common/temporal.polyfill.ts
  • packages/library/src/common/webtoken.library.ts
  • packages/tempo/bin/push-docs.sh
  • packages/tempo/doc/tempo.plugin.md
  • packages/tempo/src/plugin/term/term.util.ts
  • packages/tempo/src/support/support.enum.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/support/support.license.ts
  • packages/tempo/src/support/support.util.ts
  • packages/tempo/src/tempo.class.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/tempo/src/support/support.enum.ts
  • packages/tempo/bin/push-docs.sh
  • packages/library/src/common/webtoken.library.ts
  • packages/library/src/common/buffer.library.ts
  • packages/tempo/src/support/support.license.ts

Comment thread packages/tempo/src/support/support.init.ts Outdated
Comment thread packages/tempo/src/support/support.util.ts Outdated
@magmacomputing magmacomputing merged commit b43bc90 into main Jun 7, 2026
2 checks passed
@magmacomputing magmacomputing deleted the feature/registry-support branch June 7, 2026 10:17
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.

1 participant