Skip to content

DAR Backup

Cursor Agent edited this page Jun 22, 2026 · 18 revisions

DAR File Backup System

The repo dars/ tree preserves versioned DAR (DAML Archive) files for OpenCapTable uploads. Since DAML builds are only deterministic when using the exact same compiler version, we store the exact bytes of published packages here.

As of #217, dars/ and dars.lock keep only OpenCapTable-vNN backups (currently v34 on-chain, v35 0.0.2 local backup with networks: []). Older OCP DARs and packages maintained in fairmint/daml are not backed up in this tree—use that repo (and its lockfiles / release process) for those artifacts. #216 moved non-OCP sources out of this repo; #217 aligns checked-in backups with the OCP-only layout.

Not the same as the npm DAR: The published JS package @fairmint/open-captable-protocol-daml-js also ships a copy of the current OpenCapTable DAR under a stable export path (opencaptable.darpublished-dars/OpenCapTable.dar; see the NPM Publishing section on Home, including getOpenCapTableDarPath() / resolveOpenCapTableDarPath(), env var OPEN_CAP_TABLE_DAR_PATH, and sibling overrides). That artifact is for downstream tooling tied to the npm release, while dars/ is the canonical backup of deployed OpenCapTable package/version pairs for verification and rollback.

Why We Need This

  1. Package verification - Canton validates package hashes; rebuilt packages have different hashes
  2. Reproducibility - Ensures we can always redeploy the exact same artifact
  3. Rollback safety - Allows redeploying a known-good version if needed

Directory Structure

The exact set of backed-up artifacts is defined by dars/dars.lock (and the matching paths under dars/). Example layout:

dars/
├── dars.lock                          # Hash manifest for CI verification
├── OpenCapTable-v34/
│   └── 0.0.1/
│       └── OpenCapTable-v34.dar       # On-chain (devnet + mainnet)
├── OpenCapTable-v35/
│   ├── 0.0.1/
│   │   └── OpenCapTable-v35.dar       # Superseded local backup
│   └── 0.0.2/
│       └── OpenCapTable-v35.dar       # Current local backup (not yet uploaded)
└── …                                  # Additional OpenCapTable-vNN/<version>/ rows per dars.lock

There is no dars/README.md in the repo — this wiki page and dars.lock are the references.

Related archives: Historical DAR backups for packages that are no longer stored under this repo’s dars/ tree may also be maintained in Fairmint/daml alongside its lockfile.

Using the Backup System

After a Successful Upload

Back up the DAR file after uploading to mainnet:

npm run backup-dar -- --package OpenCapTable-v35 --version 0.0.2

This will:

  1. Copy the DAR from .daml/dist/ to dars/{package}/{version}/
  2. Compute and store the SHA256 hash in dars.lock
  3. Fail if the DAR already exists (prevents accidental overwrites)

Verifying DAR Integrity

Check that all DAR files match their recorded hashes:

npm run verify-dars

CI Integration

  • check-dars.yml — runs on pushes that change dars/** (or the workflow file). Executes npm run verify-dars to ensure hashes match dars.lock.
  • release.yml — the package tag release workflow runs npm run backup-dar during build, then npm run verify-dars before publish; it commits updated dars/ and dars.lock back to main when they change.

PRs that modify DAR files without a matching dars.lock update will fail verification.

dars.lock Format

The dars.lock file contains SHA256 hashes and metadata for all backed-up DARs:

{
  "version": 1,
  "packages": {
    "OpenCapTable-v34/0.0.1/OpenCapTable-v34.dar": {
      "sha256": "abc123...",
      "size": 12345,
      "sdkVersion": "3.4.10",
      "uploadedAt": "2026-01-09T12:00:00Z",
      "networks": ["mainnet", "devnet"]
    }
  }
}

Git LFS

DAR files are stored using Git LFS to keep the repository performant. The .gitattributes file configures this automatically.

Modifying DARs

Never modify a DAR file directly. If you need to deploy a new version:

  1. Update the DAML source code
  2. Bump the version in daml.yaml
  3. Build and upload the new version
  4. Back up the new DAR with npm run backup-dar

The CI will reject any PR that modifies existing DAR files without a corresponding version bump.

Troubleshooting

Mainnet upload: NOT_VALID_UPGRADE_PACKAGE (Splice / lineage)

Canton’s default upload path vets new packages immediately. If the new DAR is not an LF-valid upgrade of an already-vetted same package name (often because embedded splice-amulet changed between builds), upload fails with NOT_VALID_UPGRADE_PACKAGE.

Sketch of the escape hatch: upload with --no-vet, then vet the new package id via POST /v2/package-vetting with operator force flags when your topology allows it. Regenerate JS (npm run codegen) after any splice-amulet data-dependency change so bundled imports match the built DAR. For CantonPayments and other multi-package lineages, follow the playbooks documented with fairmint/daml. In this repo, npm run vet-package-allow-incompatible-upgrade is a thin helper around forced vetting (see script header in scripts/vet-package-allow-incompatible-upgrade.ts).

"DAR already exists" error

If you see this error when running backup-dar, it means the DAR for that package/version already exists. This is intentional—we never overwrite backed-up DARs. If you need to deploy changes, bump the version number.

"Hash mismatch" error in CI

This means a DAR file has been modified without updating dars.lock. Either:

  1. Restore the original DAR file
  2. If intentional, update dars.lock with npm run verify-dars -- --update

Git LFS not working

Make sure Git LFS is installed and initialized:

git lfs install
git lfs pull

References

Clone this wiki locally