Repository navigation
Distribute the registry as a runnable dependency #157
Description
Objective
Make this repository installable as a git dependency at a tag and expose a
single bin that starts the registry HTTP service, so that canton-dappbooster
can run it in its local stack with the pin recorded in a lockfile.
Rationale
canton-dappbooster already consumes @bootnodedev/canton-wallet-service this
way. It cannot consume this repository, for three independent reasons:
registry/isprivate: true, lives in a subdirectory, and exposes no bin.
Neither npm nor pnpm can install a git dependency from a subdirectory.- The root
postinstallrunsscripts/fetch-dep.sh, which wantsdpm, a JDK
17+,gitand a 123 MB clone ofcanton-network/splice. npm runs a
dependency'spostinstallduring the consumer's install, so every consumer
would pay for the whole Daml toolchain in order to start an HTTP service that
never reads a DAR. On a machine withoutdpmthe install does not slow down,
it fails. - Nothing here is packable. The root manifest has no
bin, nofiles, declares
none of the service's runtime dependencies, and itstypeiscommonjswhile
the service it would ship is ESM.
The workaround available today is for the consumer to clone this repository at a
tag and run the service out of the working copy. That works, but it puts the pin
in a shell variable rather than a lockfile, and it still needs the Daml
toolchain on the consumer's machine.
Scope
In scope:
- The root
package.jsonbecomes the npm face of the repository: scoped name,
bin,files, the service's runtime dependencies, and"type": "module". postinstallis deleted. Vendoring the Splice DARs becomes an explicit
npm run setup, which is the command that already did it.- The service is compiled at install time by
prepare. Nothing prebuilt is
committed. - A guard that fails when the root and
registry/manifests disagree on a
dependency. - A smoke test that packs, installs and runs the package the way a consumer
does, with no participant and no Daml toolchain. - A CI job that runs both.
README.md,RUNBOOK.md,ARCHITECTURE.md,CLAUDE.mdandSPEC.md
updated for all of the above.- The npm version goes to
0.2.0, andv0.2.0is cut after merge so that the
README's pin resolves.
Out of scope:
- Publishing to the public npm registry. The package is consumed from git, the
same way the wallet service is. - A container image.
- Any change to the service's routes, configuration, defaults or behaviour.
- Any change to the Daml packages, the DAR, or the release artifact flow.
daml/canton-token-forge/daml.yamlstays at0.0.1. - Converting the repository to npm workspaces. A consumer installing a git
dependency gets that package's own dependencies and nothing else, so
workspaces buy nothing here.
Architecture & technical considerations
The model is @bootnodedev/canton-wallet-service: public on GitHub, absent from
the public npm registry, consumed as a git dependency so the tag lands in the
consumer's lockfile. Its root manifest is the service (bin at
dist/server.js, files: ["dist", ".env.example"], prepare runs tsc). The
one difference here is that our service is not at the root, so the root manifest
ships a subdirectory's build output.
Five facts, each established by running it against the tree, shape the work:
- npm packs no nested manifest and no
node_modules.registry/package.json
does not travel in the tarball. So the four runtime dependencies must be
declared in the root manifest, because nothing else can be present for the
bin's imports to resolve against, and the ESM marker has to be on the root
manifest too. - A nested
.gitignoreoutranks the rootfilesallowlist for paths inside
it; the root.gitignoredoes not.registry/.gitignorecurrently ignores
dist, which silently empties the package:files: ["registry/dist"]ships
zero files, and the consumer installs a bin pointing at nothing. Moving that
one rule up to the root.gitignorefixes it and leaves git's behaviour
identical. express-openapi-validatorreads its spec lazily. A spec file left out of
the tarball does not fail the boot: the service starts and answers
GET /healthz200, and only fails the first API request with
500 openapi.validator: spec could not be read. Any check that the specs
shipped has to inspect the archive or issue a real API request.- An unreachable participant does not stop the boot. Only two participant
answers are fatal, both attributable to our own configuration; everything else
warns and continues, and/healthznever touches the ledger. That is what
makes an install smoke test possible with no participant running. tscpreserves a shebang, so the bin target needs no wrapper file, and
npm sets the exec bit when it links it.
The main risk this introduces: the root and registry/ manifests will name
overlapping packages, and drift between them means a consumer resolving a
different express than the suites ran against. Mitigated by a guard that fails
CI rather than a consumer's install.
Dependencies
- Blocks:
canton-dappboosterrunning this registry in its local stack. - Blocked by: nothing.
- This repository is private, so a consumer's install needs git credentials for
github.com. That is a documented precondition, not something this epic can
remove.
Issue breakdown
- Install the repo without the Daml toolchain #158 Install the repo without the Daml toolchain
- Expose the registry as the root package's bin #159 Expose the registry as the root package's bin
- Guard the two manifests against dependency drift #160 Guard the two manifests against dependency drift
- Prove the published package installs and runs #161 Prove the published package installs and runs
- Add the package CI job #162 Add the package CI job
- Document consuming the registry #163 Document consuming the registry
Each lands as its own pull request against a shared aggregate branch; one pull
request from that branch to main closes this epic.
Acceptance criteria
- A consumer pins this repository at a tag in
dependenciesand gets a
working install with neitherdpmnor a JDK onPATH -
pnpm exec canton-token-forge-registrystarts the service, configured
entirely from the environment - The install needs no Daml dependency fetch, and nothing prebuilt is
committed - A single command in this repository proves the published package installs
and serves, and CI runs it on every change that could break it - The root and
registry/dependency lists cannot drift without failing a
check - The README documents the consumer install, the run, the required
environment, and the git-credentials precondition - Every document that describes the install lifecycle matches what it now
does -
v0.2.0is cut after merge and the pin the README names resolves
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity