documenso 1.0.0 — self-hosted document signing - #526
Conversation
Documenso 1.0.0 — open-source e-signature (v2.17.0) on a standard workload with
a bundled postgres (single-instance default, postgres-highly-available behind a
flag). No volumeset: the app tier is stateless.
Build-time probes against the pinned image and tag corrected four things:
- The published image sets no NODE_ENV, so the chart sets it. Without it the
session cookie loses its __Secure- prefix on an HTTPS endpoint, the language
cookie loses `secure`, and embedding presign tokens accept expiresIn: 0.
- cert-status.ts returns {isAvailable:true} for any NEXT_PRIVATE_SIGNING_TRANSPORT
that is not exactly `local`, INCLUDING unset — measured green with no
certificate present at all. The chart declares it explicitly.
- Telemetry is live in the published image (real PostHog key + host baked in,
startup event plus hourly heartbeat), not inert as the Dockerfile ARGs suggest.
Added a telemetry.enabled knob, default off.
- `-legacy` is not required for the .p12 at this tag: legacy, OpenSSL-3-default
and password-less files all parse through P12Signer.create.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… align private app URL Three review findings, no blockers. 1. The "Backing up the database" section deferred bucket, cloud-account and IAM setup to the postgres template README via a filesystem-relative link (../../../postgres), which resolves to nothing when this README renders standalone in the marketplace. CLAUDE.md requires cloud-resource setup to be written out. Replaced with per-provider steps: the bucket-scoped AWS IAM policy JSON (the full action list the backup image needs, including the multipart actions), the GCP roles, and the MinIO create-dictionary command — mirroring the shape calcom uses for the same pass-through. Prerequisites now lists the backup bucket/cloud account as its own optional item rather than naming a cloud account only for document storage. 2. A user setting postgres.internalAccess.type to workload-list without listing this release's own workload cuts the app off from its own database, and it fails as a boot hang rather than an error. A parent cannot inject into a subchart's list, so the chart now hard-fails at render, naming the exact link to add — mirroring the guard wordpress already has for its mariadb pass-through. type: none is refused outright. postgres-highly-available exposes no internalAccess knob, so that path needs no guard. 3. With publicAccess off and no publicUrl, NEXT_PUBLIC_WEBAPP_URL was the internal service-DNS name while the README tells users to reach the app over cpln port-forward at http://localhost:3000. That value drives the session cookie domain, so the two origins have to agree. Adopted calcom's choice and rationale (calcom/_helpers.tpl "calcom.appUrl"): the private branch is now http://localhost:3000. Verified: bare `helm template --set global.cpln.gvc=test-gvc` renders clean and is byte-identical to before apart from the changed comment block; both guard arms proven (bad list and type: none both fail with the new message, a list including the app still renders); the added create-dictionary command was executed against the org and the secret verified then deleted; every README URL resolves; the publicUrl README block still matches values.yaml byte for byte; lint clean. Briefing updated for the new default and the new guard.
…fuse the boot warning Documentation-only fixes from the live test round; no chart file changed and the default render is byte-identical. - The README claimed both `.p12` forms parse at v2.17.0. Measured false: a `-legacy` certificate leaves `Seal Document` FAILED (retried 3) with the document PENDING, while the OpenSSL-3 default completes in 20 s — same key, same certificate, same passphrase, same release. Following upstream's `-legacy` instruction produces a fully green, silently unusable install, so the README now says explicitly not to add it. - Rotation guidance now states the consequence, not just the command: a `cpln://` reference resolves at replica start and is never re-resolved. Measured 8.5 min with the old value live and `ready: true` throughout, so replacing a compromised signing certificate changes nothing without `cpln workload force-redeployment`. - Named the only surface that reports a bad certificate — the `Seal Document` row of `BackgroundJob`. The health endpoints and `cpln logs` show nothing. - Documented `⚠️ Certificate not found or not readable` as expected: upstream's start.sh probes for a certificate file while this chart supplies contents. Briefing updated with all four. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Holding this — a latent defect surfaced after it was opened.
The test round could not have caught it: Documenso also has neither protection layer today. Open Question 6 in its test report records that it makes no GVC API call and ships no A fix adding the structural confinement ( Please don't merge until the fix lands and it re-tests in a multi-location GVC. |
templates/workload-documenso.yaml rendered a bare `minScale: {{ replicas }}`
with no localOptions and no staticPlacement. A workload runs in EVERY location
its GVC has, so a default install into a multi-location GVC started one
Documenso per location, each bound by service DNS to its own local Postgres —
separate databases, invisible to each other, every status surface green. The
identical shape was measured on calcom in a 3-location GVC; documenso's test
round ran in single-location test-gvc-3 and could not have observed it.
Apply the CLAUDE.md structural confinement: `defaultOptions.minScale/maxScale:
0` with a single `localOptions` entry supplying the real per-location count, so
an undeclared location gets `desiredScale: 0` and starts nothing by
construction (`This workload location is deactivated because maxScale is set to
0`). Shape copied from plane 1.0.0 / calcom.
New `location` value, hard-required at render: empty, non-string and a plural
`locations` key each fail with the fix in the message.
The bundled postgres subchart is NOT covered — neither postgres nor
postgres-highly-available exposes a placement knob and a parent cannot template
a subchart's workload spec — so an extra GVC location still starts an idle
database there on its own empty volume. Said plainly in the README and briefing
rather than claiming the problem is solved.
No boot-time GVC read: the reasons, and the conditions for revisiting, are
recorded in briefings/documenso.md.
… extra one Round 2 FAIL: validateLocation checked empty/non-string/plural but never the string's SHAPE. Both '//location/aws-us-east-1' and a comma-separated list were accepted by Helm AND by the API, which stored a placement matching no real location -- so nothing ran anywhere, every location reported 'deactivated because maxScale is set to 0', and the logs were silent. The link form is the copy-paste the values comment invites: it tells the user to read spec.staticPlacement.locationLinks, whose entries ARE links. The chart is the only layer that can catch this. Doc corrections from the same round: an extra GVC location costs a LIVE idle Postgres (ready 1/1, minCpu 250m / minMemory 512Mi / 10GiB volume each), not 'a volumeset and nothing else'; and desiredScale is ABSENT on a deactivated location rather than present-and-0, so the message is the signal.
Documenso — self-hosted document signing with a real cryptographic signature, backed by Postgres and either database, S3, or S3-compatible storage.
Testing
Full matrix on
test-gvc-3, 37+ rows, every one passing except a single README sentence (fixed here). Report highlights:.p12— the headline row, not a "a file came back" check.[UNPROVEN]assumption: a presigned PUT signed by an identity's temporary credentials. Upload returns 200, object lands in the bucket, presigned GET reads it back.postgresHA.enabledon a fresh install.HOSTNAMEbind trap that madelangfuseunreachable through a port-forward does not apply at this tag.Cleanup was verified by diffing the GVC spec against a recorded before-state, not by trusting an exit code.
Two findings worth reading
The published image ships live PostHog telemetry credentials (
NEXT_PRIVATE_TELEMETRY_KEY,NEXT_PRIVATE_TELEMETRY_HOST). The Dockerfile'sARGdefaults are empty, so upstream release CI sets them — telemetry is on by default upstream. The chart shipstelemetry.enabled: falseand injectsDOCUMENSO_DISABLE_TELEMETRY.Three separate certificate defects all present as a fully green deployment. Neither
/api/health,/api/certificate-status, norcpln logsreports them. The README now names the only surface that does — aBackgroundJobquery — and drops a previous claim that the failure appears in the workload log, which testing disproved.The README's
-legacyclause was the round's only FAIL: it repeated upstream's OpenSSL instruction, which atv2.17.0yields a silently unusable install. Corrected, with the failure mode named.Known, and not this template's to fix
render-vs-storedreports 0 differences for every resource this chart authors. Nine differences remain inside the vendoredpostgres3.4.1 workload, which sends a partialdefaultOptionsblock and lets the API backfill the rest. A parent chart cannot template a subchart's workload spec.The same nine appeared on
calcomthis week. 13 shipped templates pinpostgres3.4.1, and that subchart is internally inconsistent — its ownworkload-backup.yamlalready declares the full block. The drift gate passes (two no-op upgrades come backUnchanged), so this is render-vs-stored only — the class the deployment UI surfaces. Flagging for a ruling: apostgres3.4.2 would fix it for every vendoring template.🤖 Generated with Claude Code