Skip to content

fix: match the server's NATS subject encoding for segments with dots - #13

Merged
sujal-maheshwari2004 merged 1 commit into
mainfrom
fix/12-subject-encoding
Oct 18, 2026
Merged

sujal-maheshwari2004 merged 1 commit into
mainfrom
fix/12-subject-encoding

Conversation

@sujal-maheshwari2004

Copy link
Copy Markdown
Contributor

What was wrong

priompt/priompt#33 changes the server's URI-to-subject mapping (internal/pubsub.Subject). Each URI segment becomes one subject token, and every byte outside [A-Za-z0-9_-] is percent-encoded with uppercase hex:

priompt://acme/support/agent  ->  priompt.acme.support.agent       (unchanged)
priompt://acme.corp/x/a.b     ->  priompt.acme%2Ecorp.x.a%2Eb

subject() in client.js still replaced / with . and left segment contents as they were. So against that server, subscribe() on a URI with a dot (or any other encoded byte) in a segment listened on a subject that never receives events.

Fix

subject() now does the same thing as the server's Subject/subjectToken. It strips the priompt:// prefix, splits on /, and percent-encodes each segment per UTF-8 byte (Go's loop works on bytes too), using uppercase two-digit hex. Dot-free URIs keep their subject, so nothing changes against current servers for them.

subject is now exported next to PromptClient so the tests can call it.

Test evidence

test/subject.test.js reuses the server's cases from TestSubjectIsInjective/TestSubjectMapping: the three collision pairs, agent-v2_x, priompt://acme.corp/x/a.b, and a non-ASCII segment.

Before the fix (main):

✖ distinct URIs map to distinct subjects        actual: 'priompt.acme.a.b'
✔ dot-free URIs keep their subject
✖ bytes outside [A-Za-z0-9_-] are percent-encoded with uppercase hex   actual: 'priompt.acme.corp.x.a.b'
ℹ pass 1
ℹ fail 2

After:

$ npm test
✔ distinct URIs map to distinct subjects
✔ dot-free URIs keep their subject
✔ bytes outside [A-Za-z0-9_-] are percent-encoded with uppercase hex
ℹ pass 3
ℹ fail 0

Cross-check against the server's own Go Subject() on the #33 branch (91eb76b): JS output equals Go output for 10 URIs (the collision pairs plus acme/café → priompt.acme.caf%C3%A9 and acme/a b/~x → priompt.acme.a%20b.%7Ex).

Real run with a server built from priompt/priompt#33, on priompt://acme/support/agent.v2 (subscribe, then publish over gRPC):

== main
published priompt://acme/support/agent.v2 5d27c91cdca3
no event within 3s
== this branch
published priompt://acme/support/agent.v2 43d6742cc6a6
event 43d6742cc6a6 "structural"

Notes

Fixes #12

🤖 Generated with Claude Code

The server now maps each URI segment to one subject token and
percent-encodes every byte outside [A-Za-z0-9_-] (priompt/priompt#33), so
priompt://acme.corp/x/a.b publishes on priompt.acme%2Ecorp.x.a%2Eb.
subject() still joined segments with "." unencoded, so subscribe() on such a
URI listened on a subject the server no longer uses. Dot-free URIs keep
their subject.

subject() is exported for the tests, which reuse the server's cases.
Adds an npm test suite (node:test) and runs it in CI.

Fixes #12

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sujal-maheshwari2004
sujal-maheshwari2004 merged commit b0eb2f1 into main Oct 18, 2026
1 check passed
@sujal-maheshwari2004
sujal-maheshwari2004 deleted the fix/12-subject-encoding branch October 18, 2026 17:55
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.

Match the server's subject encoding for segments with dots

1 participant