Repository navigation
Add @e2b/id: prefixed IDs for E2B resources - #1627
mishushakov wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: 4d95431 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
PR SummaryLow Risk Overview Reviewed by Cursor Bugbot for commit 4d95431. Bugbot is set up for automated code reviews on this repo. Configure here. |
Package ArtifactsBuilt from d06589f. Download artifacts from this workflow run. JS SDK ( npm install ./e2b-dockerfile-utils-0.1.2-prefixed-id-packages.0.tgz ./e2b-2.63.1-prefixed-id-packages.0.tgzCLI ( npm install ./e2b-cli-2.23.1-prefixed-id-packages.0.tgzCode Interpreter JS SDK ( npm install ./e2b-code-interpreter-2.9.2-prefixed-id-packages.0.tgzDesktop JS SDK ( npm install ./e2b-desktop-2.5.1-prefixed-id-packages.0.tgzID JS ( npm install ./e2b-id-0.0.1-prefixed-id-packages.0.tgzPython SDK ( pip install ./e2b_dockerfile_utils-0.1.1+prefixed.id.packages-py3-none-any.whl ./e2b-2.63.0+prefixed.id.packages-py3-none-any.whlCode Interpreter Python SDK ( pip install ./e2b_code_interpreter-2.11.9+prefixed.id.packages-py3-none-any.whlDesktop Python SDK ( pip install ./e2b_desktop-2.7.2+prefixed.id.packages-py3-none-any.whl |
ebc5708 to
27a952b
Compare
A three-character kind prefix, an underscore, and the 26-character TypeID
encoding of a UUID:
prj_7mfb0gpp6c8dsaasre0asc7n3s
sbx_01kyjhkfzbf7samagavqtvkg6s
The encoding is the one E2B's Go services use (packages/shared/pkg/id in
e2b-dev/infra, built on github.com/sumup/typeid): the 128 bits in base 32
with the lowercase Crockford alphabet, most significant digit first, so
every ID starts with 0-7 and sorts the way its UUID does. The Go suite's
own vectors are pinned here, prefix and all, so an ID minted on either
side decodes on the other to the same UUID. A leading character above 7
is rejected as overflow rather than masked, exactly as Go rejects it.
Kinds are project, workspace and secret — the three Go defines, with the
same prefixes — plus volume, sandbox, user and group ahead of it.
UUIDs are read and minted the way github.com/google/uuid does it, so
the two sides agree there too: encodeId takes exactly the four spellings
Go's Parse takes (hyphenated, urn:uuid:-prefixed, braced, bare) and
checks no version bits, and createUuid is NewV7 — a millisecond
timestamp and a 12-bit sequence bumped so every UUID a process mints is
strictly greater than the last, then 62 random bits — so IDs sort in
call order even within a millisecond.
No dependencies, and no runtime-specific API: a test asserts src reaches
for nothing but platform globals, so the package works in Workers, Deno,
Bun and browsers with no compat flags. The interop suite drives python3
over the whole corpus with an arithmetic encoder stated independently of
this code.
Wired into the release pipeline: public, versioned from 0.0.0 with an
"Initial release" changeset so the next release mints 0.1.0, gated on
the id_tests workflow in release.yml, and published by `changeset
publish` over npm's OIDC trusted publishing like every other package
here. The @e2b/id name already exists on npm as a 0.0.0 placeholder
with the trusted publisher attached, so 0.1.0 is the first real
version and publishing needs no manual step.
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
27a952b to
816170f
Compare
… @e2b/id
- decodeId and parseId throw InvalidIdError('prefix') for a non-string id
(null, a number, ...) instead of a TypeError, so callers that map
InvalidIdError to a 400 don't turn a bad JSON payload into a 500.
- Kind lookups in prefixOf and isId use own properties only, so
encodeId('toString', ...) throws InvalidIdError('kind') instead of
minting "function toString() { [native code] }_...".
- decodeId no longer slices to indexOf's -1 when the id has no separator,
which named the wrong kind for inputs like "prjx".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds tests/uuid.test.ts, which exercises uuid.ts on its own instead of
through encodeId/createId:
- uuidToBytes: exact bytes, every hex digit in both cases, agreement with
an independent formatter over the shared corpus, and each of Go's four
forms probed one character short, one long and with a bad digit.
- bytesToUuid: all 256 byte values, the corpus, Buffers and Uint8Arrays
from another realm, and wrong lengths.
- createUuid, on a fresh module per test so the monotonic state never
leaks between them: version and variant on every mint, the 48-bit
timestamp at 0, 2^32 +/- 1 and 2^48 - 1, random bits confined to rand_b,
the sequence resetting on a new millisecond, and carry on overflow.
The tests caught two input-validation bugs, both now InvalidIdError('uuid'):
uuidToBytes threw a TypeError for a Symbol (from interpolating it into the
message), and bytesToUuid threw a TypeError for null and formatted plain
arrays and Uint16Arrays with values above 255 as "undefined".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stack: 1 of 2. This is the JavaScript half; #1628 adds the Python twin on top. Split for review — this PR is self-contained and its tests pass with
packages/python-idabsent.@e2b/idgives every service and SDK one spelling for a resource ID: a three-character kind prefix, an underscore, and the 26-character TypeID encoding of a UUID — the format E2B's Go services emit and accept (packages/shared/pkg/idin e2b-dev/infra, built ongithub.com/sumup/typeid). No dependencies, and no runtime-specific API — a test assertssrcreaches for nothing but platform globals, so it works in Workers, Deno, Bun and browsers with no compat flags.The encoding is the UUID's 128 bits in base 32 with the lowercase Crockford alphabet (
0-9a-zminusi,l,o,u), most significant digit first, left-padded to 26 digits. 26 digits hold 130 bits, so the first character carries two zero bits and is always0–7; anything above is rejected asoverflowrather than masked, exactly as Go rejects it. The digits are the bits in order, so IDs sort like their UUIDs: a UUIDv7's IDs are ordered by mint time, and a batch minted together shares a long prefix.Part of SDK-303
Usage
Id<K>is a template literal type, so a mismatch is a compile error andisIdnarrows:Errors carry a
reason('kind' | 'prefix' | 'length' | 'alphabet' | 'overflow' | 'uuid') plusactualKind, so callers branch on a field rather than on message prose.projectworkspacesecretvolumesandboxusergroupprjwrksecvolsbxusrgrpproject,workspaceandsecretare the kinds Go defines, with the same prefixes; the other four are ahead of it.Notes for reviewers
78ab8bb55); an earlier revision of this PR implemented the pre-move format. The golden vectors now include every vector fromobject_test.go, prefix and all — including the "legacy body" case Go pins (prj_6zhag5xcjyf4sadahkmb6xrfqf→df8aa05e-…), which exists precisely because the two alphabets overlap and a string in the old format can decode silently to a different UUID under the new rules.0.1.0rejects a structurally valid ID for a kind added later. Known and accepted for now, to be handled before an eighth kind ships.apiidboundary types take a UUID or a public ID; that is an HTTP-input convenience, not part of the codec, and this package implements the codec.0.0.0with an "Initial release" changeset so the next release mints0.1.0, gated on theid_testsworkflow inrelease.yml, and published bychangeset publishover npm's OIDC trusted publishing like every other package here. The@e2b/idname already exists on npm as a0.0.0placeholder with the trusted publisher attached, so0.1.0is the first real version and the release needs no manual step.Verification
129 tests, plus lint/typecheck/build clean. Beyond the suite: the built
distcontains zeronode:imports, and the interop suite drivespython3over the whole 1306-value corpus with an arithmetic encoder stated independently of this code (int.from_bytesand the alphabet, nothing else).CORPUS_DIGESTis the cross-implementation contract that #1628 pins from the other side.🤖 Generated with Claude Code