Upstream publishes the checksums asset as a plain "checksums.txt" at
the release root, not "ntfy_<VER>_checksums.txt". The version-prefixed
URL we were constructing 404'd, so InstallNtfy bailed in the
download-binary step and ntfy never landed even after we wired
InstallNtfy into the pre-built install path.
Verified against the v2.11.0 release assets list. If a future version
changes the naming convention, the install will 404 loud and this URL
gets bumped in the same PR as ntfyVersion.
VERSION bumped to 0.122.18.
Phase 2b auto-detects pre-built archive mode and routes to
installFromPreBuilt(). That path copies bundled binaries (caddy, orama,
gateway, …) into place but never called InstallNtfy() — because ntfy
is downloaded from upstream github, not bundled. Result: on devnet
(which always uses pre-built mode), ntfy never installed even though
the always-on code path in installFromSource() was correctly wired up.
Fix: add InstallNtfy() call to installFromPreBuilt right after the
binary deploy + setCapabilities steps, before disableResolvedStub
runs. Ordering matters because Phase 4's ConfigureNtfy chowns
/etc/ntfy/server.yml to the ntfy user, which needs to exist.
VERSION bumped to 0.122.17.
ntfy is now part of the standard node install, just like Caddy. The
binary, /etc/ntfy/server.yml, and the Caddy push.<dnsZone> reverse-
proxy block are written unconditionally on every node, and the
ntfy.service starts as part of the standard service order.
Why uniform: ntfy listens on 127.0.0.1:NtfyListenPort only, reachable
exclusively via the local Caddy reverse-proxy block. Nodes that don't
serve a public push.* DNS entry just have an idle ntfy with no
inbound traffic — zero operational cost, zero attack surface change.
Removing the flag means no per-node toggling, no preference drift
between nodes, no "did we remember to set --with-ntfy" mistakes when
DNS topology changes (e.g. promoting a node to nameserver later).
Removed:
- NodePreferences.NtfyHost (yaml: ntfy_host)
- ProductionSetup.isNtfyHost field, SetNtfyHost, IsNtfyHost
- install/flags.go --with-ntfy + NtfyHost field
- upgrade/flags.go --with-ntfy + NtfyHost field + isFlagPassed helper
(was only used for --with-ntfy tri-state semantics)
- upgrade/orchestrator.go preference-load and persist for ntfy
- upgrade/remote.go --with-ntfy forwarding
Phase 2 always calls InstallNtfy.
Phase 4 always calls EnableCaddyNtfyProxy + ConfigureNtfy.
Phase 5 always enables ntfy.service.
Phase 5b always starts ntfy.service.
VERSION bumped to 0.122.16.
`orama node upgrade --node <ip> --with-ntfy --restart` parsed the flag
locally but `upgradeNode()` ran a hardcoded
`orama node upgrade --restart` on the remote — dropping --with-ntfy,
--nameserver, --force, and --skip-checks on the floor. The remote
orchestrator then read the SAVED preference (or default false for
nameserver/ntfy), so operator overrides like enabling ntfy on a
nameserver were silently ignored. Bug surfaced in devnet today:
running --with-ntfy reported success but ntfy was never installed.
Fix forwards the four passthrough flags to the remote command,
preserving the tri-state semantics for the pointer flags (nil = honor
saved preference; non-nil = explicit override).
VERSION bumped to 0.122.15.
Migration 028: namespace_push_credentials
- Per-(namespace, provider) AES-256-GCM encrypted credential blob.
- Generic schema — apns/ntfy/expo/future plug in with zero migration.
- Separated from migration 026's namespace_push_config (preferences vs
credentials, different access patterns).
pkg/push/credentials
- Manager + Registry + RQLite store; HKDF purpose "namespace-push-credentials"
via pkg/secrets. Provider Validator interface for per-provider schema.
pkg/push/providers/apns
- Apple Push Notification service direct provider (no Expo proxy).
- Validator + dispatcher; credentials are p8 signing key + key_id + team_id.
pkg/push/providers/ntfy/credentials.go
- ntfy credential schema (auth_token + default topic). Used both with
the public ntfy.sh and our self-hosted instance.
pkg/environments/production/installers/ntfy.go
- Self-hosted ntfy server installer. Binary, system user, hardened
/etc/ntfy/server.yml, systemd unit. Listens on 127.0.0.1:NtfyListenPort
only — Caddy is the only public path.
pkg/environments/production/installers/caddy.go
- Emit reverse_proxy block for push.<dnsZone> -> 127.0.0.1:NtfyListenPort
when operator enables ntfy on a node.
CLI: install/upgrade orchestrators learn a new "ntfy" install/preserve
phase; flag gating in install/flags.go + upgrade/flags.go.
Gateway handlers/push/credentials_handler.go
- GET/PUT/DELETE /v1/namespace/push-credentials/{provider}.
- PUT validates against provider Validator before encrypting and storing.
- GET returns a redacted view (booleans + non-secret fields only).
Push manager: provider resolution now also consults
namespace_push_credentials before falling back to YAML defaults.
Docs: core/docs/PUSH_NOTIFICATIONS.md walks through end-to-end setup.
VERSION bumped to 0.122.14.
HTTP/2 forbids the `Connection: Upgrade` and `Upgrade: websocket`
headers per RFC 7540 §8.1.2.2. With h2 advertised at the listener,
ALPN negotiates h2 for TLS-capable clients, the WS-upgrade request
arrives at Caddy with those headers stripped, and Caddy forwards a
plain HTTP/1.1 GET to the gateway. The gateway's `isWebSocketUpgrade(r)`
then returns false, the `?api_key=` / `?jwt=` query-string WS-auth
fallback never runs, and clients see 401.
RFC 8441 ("Bootstrapping WebSockets with HTTP/2") fixes this, but iOS
RN and most other mobile WS libraries don't implement it. Until they
do, h1 is the only protocol that keeps WS auth working.
Trade-off: lose h2 multiplexing on plain HTTP traffic. Acceptable for
an API gateway whose dominant workload is REST + WebSocket — neither
benefits much from h2 streams.
caddy_test.go adds a regression guard so anyone re-enabling h2 in the
listener protocols fails CI loud.
Also (separate, was uncommitted): pkg/cli/build/builder.go now reads
VERSION from the repo-root /VERSION file first, falling back to
parsing the Makefile only if absent. The previous Makefile-only path
broke after VERSION moved to /VERSION (Makefile got `$(shell cat ...)`
which the CLI builder pulled in literally).
VERSION bumped to 0.122.13.
Per-namespace rate-limit config (feature #69)
- Migration 027: new `namespace_rate_limit_config` table
(namespace PK, requests_per_minute, burst, audit metadata).
- pkg/ratelimit: Manager + RQLite ConfigStore + types. Same pattern
as the push config in bug #220's follow-up — LRU cache, invalidate
on PUT/DELETE, falls back to YAML defaults when no row exists.
- pkg/gateway/handlers/ratelimit: GET/PUT/DELETE /v1/namespace/rate-limit.
PUT requests are rejected if they exceed the operator's configured
ceiling (MaxRequestsPerMinute / MaxBurst) — tenants self-serve but
cannot raise their quota past the cap.
- pkg/gateway/rate_limiter.go: per-namespace lookup, default fallback.
- pkg/gateway/middleware.go: WS JWT middleware (middleware_ws_jwt_test.go).
- pkg/gateway/auth/service.go: refresh-token rotation hardening with
regression test in refresh_rotation_test.go.
AI agent instructions
- Add AGENTS.md, CLAUDE.md, .github/copilot-instructions.md (DeBros v0.2.0
baseline).
DeBros rules bumped to v0.2.0 (sha bb6e6ef).
VERSION bumped to 0.122.12.
Workflow hardening based on the four-cycle release-debugging session:
Centralized versioning
- Add /VERSION at repo root as single source of truth.
- core/Makefile reads VERSION via `$(shell cat ../VERSION)`.
- Add `make bump VER=X.Y.Z` target that updates /VERSION and syncs
sdk/package.json in one shot.
Version mismatch guards
- All three release workflows (release.yaml, release-apt.yml,
publish-sdk.yml) now verify the release tag matches /VERSION at the
very first step. Stale-VERSION releases fail fast with a clear hint
to run `make bump`.
GoReleaser v2 migration
- Upgrade goreleaser-action v5 -> v6 (pinned `~> v2`).
- Add `version: 2` to .goreleaser.yaml.
- Migrate to v2 syntax: `archives.format` -> `formats: [...]`,
`brews.folder` -> `directory`, `snapshot.name_template` ->
`version_template`, `builds`-style references replaced with `ids:`.
- `before.hooks` can use map syntax again (v2 supports it).
Homebrew tap on stable only
- `brews.skip_upload` is now `'{{ if .Prerelease }}true{{ else }}false{{ end }}'`.
- Stops nightly releases from polluting the tap and from hitting 401
on stale HOMEBREW_TAP_TOKEN. Stable main releases still publish.
CI on every push
- New ci.yml runs `go vet` + `go test -race` on the core module and
typecheck/build/unit-tests on the SDK for every push to main/nightly
and every PR. version-sanity job warns when /VERSION and
sdk/package.json drift.
Version bump for next pipeline test
- /VERSION: 0.122.8
- sdk/package.json: 0.122.8
The repo moved from DeBrosOfficial/network to DeBrosDAO/orama.
GoReleaser was uploading artifacts to the old URL and getting 307
redirects, then retrying until secondary rate limits kicked in.
- release.github.owner/name: DeBrosOfficial/network -> DeBrosDAO/orama
- brews.repository.owner: DeBrosOfficial -> DeBrosDAO
- all homepage URLs updated
- bump VERSION to 0.122.7 for fourth pipeline test
- goreleaser nfpm contents pointed to ./core/README.md which doesn't
exist; switched to repo-root ./README.md
- bump VERSION to 0.122.6 for third pipeline test
- goreleaser: 'cd core && go mod tidy' didn't work — hooks run via exec,
not shell. Switched to 'go -C core mod tidy' which is shell-free.
- release-apt: remove redundant mv that renamed file to itself
(PKG_NAME and target name were identical, dpkg-deb already named it
correctly)
- bump VERSION to 0.122.5 for second pipeline test
- goreleaser: switch hooks to v1 string syntax (was map syntax, caused
yaml unmarshal error on action v1.26.2)
- release-apt: build ./cmd/cli and ./cmd/node as packages (was building
single .go files, missed sibling files → undefined: runCLI)
- publish-sdk: remove main-only guard; nightly releases now publish to
npm with --tag nightly (stable releases still go to @latest)
- bump VERSION to 0.122.4 for first end-to-end release pipeline test
- Change RQLite consistency level from `none` to `weak` to ensure reads
route to the leader and prevent stale data reads (fixes#235)
- Add `normalizeColumnKey` to allow snake_case SQL columns to map to
CamelCase Go struct fields automatically (fixes#65)
- Add comprehensive unit tests for DSN generation and column mapping
- Add `namespace_push_config` table for per-namespace provider settings
- Introduce `cluster_secret_path` to enable deterministic JWT signing and
AES-256-GCM encryption for push credentials
- Update gateway config to support per-namespace overrides of push
notification providers (ntfy/Expo)
- Bump version to 0.122.3
- bump version to 0.122.2
- document schema migration invariants and push notification configuration
- add serverless host function aliases and v2 database API documentation
- introduce schema roundtrip test to prevent migration drift
- Add "orama" to the list of host module registration names to support
common developer intuition and prevent instantiation errors.
- Add comprehensive regression tests to ensure all aliases ("env",
"host", "orama") remain registered.
- Update SDK documentation to clarify import conventions and alias
support.
- Add `contract.go` to manage and validate embedded SQL migrations
- Introduce `AssertSchema` to verify database version at startup
- Include `SchemaMismatchError` with actionable recovery instructions
- Add comprehensive unit tests for version parsing and validation
- Add migrations for per-namespace publish sequences and persistent WebSocket function settings
- Integrate PersistentWSManager and WSBridge into the gateway dependency graph
- Upgrade serverless engine to use a multi-tier rate limiter
- Update JWT claims to support custom application-defined fields
- Add --fanout flag to push command for server-to-server deployment
- Implement agent forwarding for efficient multi-node distribution
- Update landing page scene heights and section padding for mobile devices
- Replace CLI-based rootwallet calls with agent-based communication
- Update production provisioner to support sudo-based service management
- Add API key-to-wallet resolution for gateway operator handlers
- implement `nodes`, `rollout`, `ssh`, and `status` commands
- add `migrate-conf` utility to register existing nodes with the gateway
- update database schema to support operator wallet tracking for nodes
- support upsert in AddEnvironment, no-op RemoveEnvironment if absent
- fallback active env to devnet on remove, add tests
- integrate with sandbox create/destroy, ignore core/plans/
- add monorepo Makefile delegating to sub-projects
- update CI workflows, GoReleaser, gitignore for new structure
- revise README, CONTRIBUTING.md for monorepo overview
- bump Go to 1.24