2026-06-12 — demarkus-library deploy manifests + CI/release
Roadmap item 1 (deploy manifests), branch feature/deploy-manifests, awaiting Fritz commit/PR.
Shipped (working tree)
.goreleaser.yml(root): single-module → plainvtags, NO monorepo block (unlike demarkus). Usedarchives.idsnotarchives.builds— deprecated since goreleaser 2.8 (demarkus repo still on old syntax;goreleaser checkfails locally on it). Addedvar version = "dev"to main.go for the-X main.versionldflag.Dockerfile(root): COPY-only overdist/docker/<arch>/staged binaries (no QEMU compile),distroless/static-debian12:nonroot— CA certs needed for outbound HTTPS to broker. EXPOSE 8080/tcp.deploy/helm/demarkus-library/: mirrors broker chart conventions. Key divergences:replicaCount: 1+strategy: Recreate— sessions in-memory; rolling update = login flapping. PDB default-off (minAvailable 1 would block drains at 1 replica).- Env-based config (no config.yaml Secret like broker). Chart-managed
-oauthSecret only for cleartextlibrary.broker.clientSecret;existingSecretRefmode for production.checksum/secretannotation only in cleartext mode. demarkus-library.validatehelper mirrors NewAppConfig startup validation at render time (transport enum, broker-mode required fields, secret mutual exclusion, quic host).- NetworkPolicy egress: DNS + TCP 443 (broker) + UDP 6309 (
networkPolicy.quicEgressPort, federation/quic dials). - Probes both hit
/health(only endpoint; broker has /healthz+/readyz). automountServiceAccountToken: false(library never talks to kube-apiserver, unlike broker).- 23 helm-unittest tests (deployment/secret/ingress suites) pass.
.github/workflows/ci.yml: paths-filter (app/charts), golangci-lint v2.9.0 action, go test/vet/build, goreleaser check, helm lint+unittest..github/workflows/release.yml: test → semver (PaulHatch, tag_prefixv, no change_path — single module, chart-only commits must bump too) → tag + goreleaser-pro + stage binaries + buildx multi-arch (amd64/arm64/armv7) → ghcr.io/latebit-io/demarkus-library + helm chart to oci://ghcr.io/latebit-io/charts, version==appVersion==image tag.- Lint cleanup: 13 errcheck issues fixed with explicit
_ =discards (demarkus convention) in broker.go, oauth.go, 2 test files. Default golangci-lint now 0 issues.
Deferred / decisions
- demarkus's strict
.golangci.yml(gocritic/revive/gocyclo/modernize) NOT adopted — 18 issues would need fixing (mostly gocritic style in tests). CI uses lint defaults. - Repo secret needed before first release:
GORELEASER_KEY(goreleaser pro).GITHUB_TOKENcovers ghcr. - Verified locally: go test ✓, golangci-lint 0 issues ✓, goreleaser check ✓, snapshot build + version stamp ✓, helm lint ✓, helm template (7 resources) ✓, 23 unittest ✓.
Next
- Fritz: commit, PR, add GORELEASER_KEY secret.
- Roadmap item 2: drop broker rateLimit.tokens to ~30/min burst ~15 (demarkus repo AppSet values).
- Then rendering upgrades (chroma first).
Correction: GORELEASER_KEY is an org-level (global) secret — already available to this repo, no per-repo setup needed.
Module-path migration to latebit-io (later same day)
demarkus merged the rename (15cc18b fix(package): latebit → latebit-io, tags
client/v0.12.40 + protocol/v0.7.13, proxy-resolvable — verified). Library
follow-up (working tree on top of 712511f "feat(CI): added deploy manifests"):
- Imports rewritten
github.com/latebit/demarkus/→latebit-io; go.mod replaces DROPPED, now requires client v0.12.40 + protocol v0.7.13 (tagged, fetchable — no sibling checkout needed anywhere). - Library's own module renamed too:
module github.com/latebit-io/demarkus-library(same latent mismatch;go mod edit -module+ import sweep). Gotcha: renaming internal imports before the module line makesgo mod tidyfetch the repo from the proxy as an external dep — fix module line first. - CI/release sibling-clone steps removed from both workflows.
- Verified: build ✓, tests ✓, lint 0 ✓, vet ✓, goreleaser check + snapshot ✓.
The 2026-06-12 sibling-clone entry in debugging.md is now historical.
PR #10 review response (CodeRabbit, 11 findings — all addressed)
Workflows: actions pinned to commit SHAs (tag comments kept) · ci.yml top-level
permissions: contents: read · release.yml write scopes moved to release job
only · non-cancelling concurrency: release-${ref} (semver/tag race) ·
release test job now also runs helm lint+unittest (chart-only push can't ship
broken chart) · if: failure() rollback step deletes release+tag so a failed
publish doesn't burn the version (tag must still exist BEFORE goreleaser —
GORELEASER_CURRENT_TAG).
Chart: validate helper trims all presence checks (matches NewAppConfig trim;
whitespace-only fails at render not CrashLoop) + new cleartextSecret helper
shared by secret.yaml/deployment.yaml · automountServiceAccountToken: false
on POD spec (held SA-only before; broke when serviceAccount.create=false) ·
NetworkPolicy ingress adds same-namespace podSelector: {} (default install
was unreachable — ingress.enabled defaults false) · NOTES insecure warning
gated on quic OR federation — NOT the reviewer's exact ask (move under quic
branch): DEMARKUS_INSECURE also governs broker-mode federation QUIC dials, so
quic-branch-only would hide a real warning.
Code: session_test.go setup Save now t.Fatalf on error.
24 chart tests (added whitespace-trim regression), lint 0, go tests pass.
PR #10 outside-diff comments (2, both fixed)
- release job gated
github.ref == 'refs/heads/main'— workflow_dispatch from a feature branch could otherwise tag + publish unmerged code. - goreleaser-action
version: latest→"~> v2"in both workflows (bounded drift).
Roadmap item 2 — broker rate limit back down
demarkus-knowledge-system-deploy branch fix/broker-rate-limit-down
(uncommitted): apps/demarkus-broker/applicationset.yaml rateLimit.tokens
60/30 → 30/15, comment rewritten (session pool made reads 1 request; the old
comment's "revisit down once the library reuses its MCP session" condition is
met). YAML validated. ArgoCD auto-syncs on merge (automated + selfHeal).
Roadmap item 2 done pending Fritz commit/PR; next is in-cluster library
install (item 1 wrap-up), then rendering upgrades (chroma).
Rendering upgrades (a)+(b) — branch feature/rendering-chroma
Debt.md items: chroma highlighting + GFM alerts + emoji, all server-side zero JS, on one branch (uncommitted).
- Chroma (goldmark-highlighting/v2): CLASSES mode, never inline styles
(bluemonday strips
style; widening = CSS-injection surface). Policy admitschromaClassesregex on pre/code/span +tabindex="0"on pre (chroma a11y).static/chroma.cssGENERATED byinternal/adapter/inbound/web/gen_chroma_css.go(go:build ignore,go generate ./internal/adapter/inbound/web) — github light + github-dark in@media (prefers-color-scheme: dark)(site declarescolor-scheme: light dark). Generator lives OUTSIDE static/ — thego:embed static/*glob would embed+serve it. - GFM alerts (zmtcreative/gm-alert-callouts v0.8.0): emits
div.callout.callout-<kind)+.callout-title/.callout-title-text/.callout-body. Default inline-SVG icons REPLACED with emoji map (WithIcons) — svg through bluemonday would mean a dozen attr allowances.calloutClassesregex bounds kind (author-controlled via [!KIND]); data-callout deliberately stripped. CSS in page.html useslight-dark()(GitHub palette both modes). Unknown kinds render neutral; plain blockquotes untouched (test-pinned). - Emoji (yuin/goldmark-emoji): :shortcode: → unicode chars, sanitizer-inert.
- Live smoke (quic vs soul): chroma classes + css verified on roadmap doc's sh fence. goldmark bumped 1.7.8→1.7.13 by deps.
- Suite green -race, lint 0. Remaining rendering debt: mermaid + KaTeX islands (ADR 0003 concessions, later).
PR #11 review fix
chromaClasses shape pattern ([a-z]{1,3}[0-9]?) admitted non-chroma tokens
(nav/btn). Replaced with an allowlist BUILT FROM chroma.StandardTypes at
init — exact by construction, upgrade-proof (formatter reads class names from
the same table). Longest-first alternation (prefix shadowing). Tests cover
nav/btn/foo1 and mixed bg nav (whole attr value must match). Suite green.