Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d0b7e4d
feat(accounts,auth-gateway): resolve the cell's collector from the ob…
crisfiorini-oss Oct 6, 2026
7e0ee42
feat(module)!: remove the telemetry service; the cell's collector rep…
crisfiorini-oss Oct 6, 2026
faa8477
Merge remote-tracking branch 'origin/main' into feat/telemetry-servic…
crisfiorini-oss Oct 7, 2026
152fd50
fix(accounts,auth-gateway): the observability state decides; build th…
crisfiorini-oss Oct 7, 2026
2991e7b
refactor(accounts,auth-gateway): resolve the listener ports without a…
crisfiorini-oss Oct 7, 2026
2720aa8
chore(deps): bump codefly core to v0.13.0 and sdk-go to v0.3.1 (Refs …
crisfiorini-oss Oct 7, 2026
badfb6c
fix(accounts,auth-gateway): restore the generated telemetry client st…
crisfiorini-oss Oct 7, 2026
3532058
fix(vault): declare its endpoint private within the module
crisfiorini-oss Oct 7, 2026
48ced8d
fix(telemetry): require platform state outside local runtimes
crisfiorini-oss Oct 7, 2026
2651984
Merge main into the telemetry branch and bring the cleanup to its rev…
crisfiorini-oss Oct 8, 2026
dbd3382
test(telemetry): select a key service backend before checking the obs…
crisfiorini-oss Oct 8, 2026
8053510
test(accounts): declare the subject module's queues, namespaces and s…
crisfiorini-oss Oct 8, 2026
a55cc00
docs(deployment): name only the CLI support this change needs for pro…
crisfiorini-oss Oct 8, 2026
b771e74
docs(deployment): state the NetworkPolicy count the golden holds (Ref…
crisfiorini-oss Oct 8, 2026
e4ce839
refactor(accounts,auth-gateway): one telemetry variable, read by core…
crisfiorini-oss Oct 8, 2026
0085e6d
chore(telemetry): merge main and preserve collector exports
crisfiorini-oss Oct 13, 2026
171e0cf
chore(telemetry): merge current module endpoint changes
crisfiorini-oss Oct 13, 2026
c5c4452
chore(telemetry): merge main and distinguish generated output
crisfiorini-oss Oct 21, 2026
c46a4ab
fix(build): consume released Go 1.27.3 service agent
crisfiorini-oss Oct 21, 2026
462a2d8
refactor(telemetry): reuse SDK tracing and Core declarations
crisfiorini-oss Oct 21, 2026
6f5e391
fix(telemetry): remove retired workspace configuration link
crisfiorini-oss Oct 21, 2026
4c9a9a6
test(telemetry): isolate SDK initialization from configuration tests
crisfiorini-oss Oct 21, 2026
f13ed4e
fix: consume environment-wide telemetry delivery
crisfiorini-oss Oct 21, 2026
5adf1cd
docs: describe existing ambient telemetry transport
crisfiorini-oss Oct 21, 2026
c28959e
Merge main into environment telemetry delivery
crisfiorini-oss Oct 22, 2026
4ec66a5
fix(security): consume patched Next.js and Sentry releases
crisfiorini-oss Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .claude/skills/run-the-starter-locally/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ description: Boot this module's whole service graph on a developer machine — w

# Running the starter locally

The graph is vault → store → cache → telemetry → accounts → auth-gateway →
frontend, plus marketing. One command boots all of it with a fake-auth fixture:
The graph is vault → store → cache → accounts → auth-gateway → frontend, plus
marketing. One command boots all of it with a fake-auth fixture:

```bash
codefly run service --fixture dev-admin
Expand All @@ -23,6 +23,14 @@ codefly run service --fixture dev-admin
- No TTY (CI, pipes, MCP) auto-enables `--headless`.
- Docker must be running. `codefly doctor` checks prerequisites; `codefly clear`
reaps stray processes and containers between runs.
- The module ships no collector. Standard OpenTelemetry process variables
select export: `OTEL_EXPORTER_OTLP_ENDPOINT` names the collector, with
`OTEL_SERVICE_NAME` and `OTEL_RESOURCE_ATTRIBUTES` supplying identity.
CLIs implementing [CLI #1097](https://github.com/codefly-dev/cli/pull/1097)
deliver these for every service through an environment's optional `telemetry:`
block, pointing at the HTTPS operations intake.
Without an endpoint, SDK Init enables no tracing, including for `local`.
No module configuration group is required.

For a real external identity provider and the production-grade provider stack,
use the `local-dogfood` environment and its configuration groups:
Expand Down
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# protoc-gen-es emits one separator line after the final declaration.
# Keep normal whitespace checks everywhere else.
module/services/frontend/code/src/gen/** whitespace=-blank-at-eof

# Generated artifacts changed by the telemetry service removal.
# Their owning generators remain responsible for the committed outputs.
module/deployment/generated/** linguist-generated=true
module/contracts/runnables/** linguist-generated=true
module/services/telemetry/code/pkg/gen/** linguist-generated=true

# Build recipes emitted by the pinned Go service agent.
module/services/accounts/builder/** linguist-generated=true
module/services/auth-gateway/builder/** linguist-generated=true
module/services/policy-log/builder/** linguist-generated=true
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ module/services/*/nix/
/configurations/local-dogfood/error-tracking.env
/configurations/local-dogfood/error-tracking.secret.env
/configurations/local-dogfood/observability.env
/configurations/local-dogfood/observability.secret.env
/configurations/local-dogfood/abuse-protection.env
/configurations/local-dogfood/abuse-protection.secret.env
/configurations/local-dogfood/legal.env
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ in `.claude/skills/`. See [Where the depth lives](#where-the-depth-lives).
`saas-starter` is a Codefly **module**: a multi-tenant SaaS backend
(three-layer authorization, Postgres RLS, RBAC, impersonation, audit), an
authenticated Next.js product, a separately deployable marketing site, and the
supporting cache/store/vault/telemetry services. It is published as an
supporting cache/store/vault services. It is published as an
immutable module package that downstream workspaces **compose** (never fork).

- Architecture, service graph, and capability ownership: [MODULE.md](./MODULE.md)
Expand Down Expand Up @@ -173,7 +173,7 @@ Depth sits with the code that owns it:

| File | Covers |
| --- | --- |
| [module/AGENTS.md](./module/AGENTS.md) | the shipped tree: generated vs authored files, the six Go modules and how to test each, configuration groups |
| [module/AGENTS.md](./module/AGENTS.md) | the shipped tree: generated vs authored files, the Go modules and how to test each, configuration groups |
| [module/deployment/AGENTS.md](./module/deployment/AGENTS.md) | the manifests as the model, `spec.deployment`, and moving an agent version |
| [module/services/auth-gateway/AGENTS.md](./module/services/auth-gateway/AGENTS.md) | upstream registration, the composed-module REST prefix, the credentials both take |
| [module/services/accounts/AGENTS.md](./module/services/accounts/AGENTS.md) | the durable registry record, module principals, minting a module Work Context, mesh reachability |
Expand All @@ -200,7 +200,7 @@ Skills in `.claude/skills/`, loaded when the task calls for them:
such a list with a count: nothing enforces one, so two changes that each add a
step and each bump the same number merge cleanly into a total that is silently
wrong.
- Go suites live in six independent Go modules with no `go.work`
- Go suites live in independent Go modules with no `go.work`
([module/AGENTS.md](./module/AGENTS.md#go-suites)).
- Vulnerability policy: the complete audit runs non-blocking so vendor-image
findings stay in the evidence report, while a separate fail-closed step enforces
Expand Down
2 changes: 1 addition & 1 deletion CLAIM_INVENTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ must not be inferred from a row here. See
| The documented repository-specific gate list is the enforced one | RELEASE_GATES.md § Repository-specific gates; AGENTS.md | `release-gates.test.mjs` compares the table and both prose counts against `REQUIRED_GATES` | implemented | #541 |
| The complete audit runs `--fail-on-vuln=false`; a separate step enforces first-party findings fail-closed | RELEASE_GATES.md § Vulnerability policy | `.github/workflows/ci.yml` `codefly-supply-chain` | configured | Codefly + this repo |
| No artifact-writing job runs unless every mandatory gate actually succeeded | RELEASE_GATES.md § Publication gating | `scripts/ci/release-gates.mjs check` + `decide`, `release-gates.test.mjs` | implemented (#535) | this repo |
| Root `go test ./...` does not cover nested service modules | RELEASE_GATES.md, AGENTS.md | six independent `go.mod` files; there is no `go.work` | implemented (documented) | #541 |
| Root `go test ./...` does not cover nested service modules | RELEASE_GATES.md, AGENTS.md | independent `go.mod` files (the root, `module/tools`, one per Go service); there is no `go.work` | implemented (documented) | #541 |
| `main` here is the only default branch in the organization merging through a queue, and `secure-saas-platform` the only other requiring any check | RELEASE_GATES.md § The fleet beyond this repository | `scripts/ci/release-gates.mjs fleet` — operator-run: reading branch configuration needs `Administration: read`, which no workflow token can hold, so no gate can carry this | reviewed narrative | #617 |

## Public registry contract
Expand Down
12 changes: 8 additions & 4 deletions DOGFOODING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cd ~/Development/deus/codefly/module-saas-starter
codefly run service --fixture dev-admin
```

Expected graph: `vault + store + cache + telemetry → accounts →
Expected graph: `vault + store + cache → accounts →
auth-gateway → frontend` (plus marketing). Independent
services may start concurrently. If any service
hangs at "waiting for ready", check that step's `--debug` output.
Expand Down Expand Up @@ -214,12 +214,16 @@ Admin Portal integration; `IDENTITY_CLIENT_ID` and

Configure the remaining adapters as Codefly configuration groups, then start
the same Codefly-managed graph. For each of `email` (Resend),
`product-analytics` (PostHog), `error-tracking` (Sentry), `observability` and
`product-analytics` (PostHog), `error-tracking` (Sentry) and
`abuse-protection` (Turnstile), copy
`configurations/local-dogfood/<group>.env.example` and
`<group>.secret.env.example` to their Git-ignored names and fill them in
([LOCAL_DOGFOODING.md](./LOCAL_DOGFOODING.md#configure-providers-through-codefly)).
Keep `observability.env.example` as it is for local (`debug`) telemetry.
Operational telemetry has no configuration group. Use the environment's optional
`telemetry:` block with the HTTPS operations intake.
[CLI #1097](https://github.com/codefly-dev/cli/pull/1097) delivers the standard
endpoint, service identity and resource variables to every service.
With no endpoint, no traces or metrics are exported, including native local runs.
Turnstile's published test keys drive the three abuse-protection cases:

| Case | `NEXT_PUBLIC_TURNSTILE_SITE_KEY` | `TURNSTILE_SECRET_KEY` |
Expand All @@ -239,7 +243,7 @@ codefly run service --env local-dogfood
- [ ] Grant analytics consent, navigate through onboarding, and verify bounded browser plus durable backend events in PostHog.
- [ ] Withdraw analytics consent or log out. Browser capture stops immediately and identity resets.
- [ ] Trigger controlled browser and backend errors. Sentry correlates release and environment without creating performance transactions.
- [ ] With the `debug` exporter, exercise login/onboarding and observe trace/metric/log summaries from the in-graph telemetry service.
- [ ] With `OTEL_EXPORTER_OTLP_ENDPOINT` unset, exercise login/onboarding and observe stdout logs. With a reachable collector configured, confirm trace and metric delivery. An invalid exporter setting must be logged without preventing the service from starting.
- [ ] Switch Turnstile to the **fail** keys. Registration and waitlist submission fail without database writes.
- [ ] Switch Turnstile to the **replay** keys. The first deterministic verification follows Cloudflare's fixture behavior; replay rejection leaves state unchanged.

Expand Down
23 changes: 10 additions & 13 deletions LOCAL_DOGFOODING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Two Codefly inputs are intentionally independent:

| Input | Authority | Purpose |
|---|---|---|
| `--env local-dogfood` | `configurations/local-dogfood/*` | Select independently configured identity, billing, email, analytics, error, telemetry, and abuse adapters |
| `--env local-dogfood` | `configurations/local-dogfood/*` | Select independently configured identity, billing, email, analytics, error, and abuse adapters |
| optional `--fixture <name>` | `module/fixtures/<name>.yaml` | Seed a useful starting product state |

A fixture never changes the identity provider. The ordinary `local`
Expand All @@ -33,12 +33,11 @@ production/background fallback; a local port never belongs in product config.
## Configure providers through Codefly

WorkOS is the identity adapter. The production-grade dogfood stack also
includes Stripe, Resend, PostHog, Sentry, the in-graph OpenTelemetry gateway,
and Cloudflare Turnstile. Each one is a Codefly configuration group on this
includes Stripe, Resend, PostHog, Sentry, and Cloudflare Turnstile. Each one is a Codefly configuration group on this
profile: copy the committed `configurations/local-dogfood/<group>.env.example`
(and `<group>.secret.env.example`, where there is one) to the Git-ignored
`<group>.env` / `<group>.secret.env`, and fill in the values. Every group is
optional except `observability` and `email` — see the notes below. Stripe setup belongs to
optional except `email` — see the notes below. Stripe setup belongs to
the [`codefly-dev/provider-stripe`](https://github.com/codefly-dev/provider-stripe)
plugin, which validates the account, observes the webhook and projects the
`billing` group.
Expand All @@ -50,19 +49,17 @@ plugin, which validates the account, observes the webhook and projects the
| `email` | Resend |
| `product-analytics` | PostHog |
| `error-tracking` | Sentry |
| `observability` | the in-graph OpenTelemetry gateway |
| `abuse-protection` | Cloudflare Turnstile |

Validate the result with `codefly doctor workspace --env local-dogfood`.

`observability` is the one group this profile cannot skip. The `telemetry`
service declares it as a workspace-configuration-dependency, and on
`local-dogfood` the real `observability.env` / `observability.secret.env` are
Git-ignored, so there is no committed default to fall back on. Codefly skips a
declared group whose files are absent rather than failing, and the collector
refuses to start without an explicit `OBSERVABILITY_EXPORTER` — it will not
silently downgrade itself to `debug` and drop every span. Copy
`observability.env.example` as it is to keep telemetry local.
Operational telemetry uses standard process variables rather than a configuration
group. With no `OTEL_EXPORTER_OTLP_ENDPOINT`, the SDK exports no traces in any
environment, and the services build no metrics exporter. To export, use the
environment's optional `telemetry:` block with the HTTPS operations intake.
[CLI #1097](https://github.com/codefly-dev/cli/pull/1097) delivers standard OTEL
variables to every service. SDK exporter failures are
logged without stopping the service; logs always go to stdout.

`email` is required because this profile is not the `local` environment, and
accounts refuses to start there without an explicit `EMAIL_PROVIDER`: `resend`
Expand Down
9 changes: 5 additions & 4 deletions MODULE.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ capability; it does not claim that every planned provider is released yet.
| Product analytics | PostHog | The `product-analytics@1` browser/server APIs may capture registered events and perform consent-gated identify, alias, organization grouping, and privacy suppression. An event may carry a variant already evaluated by Unleash for experiment analysis. | Flag definition or evaluation, exception capture, and traces, metrics, or logs |
| Session replay | PostHog | A browser-only recorder may start after separate replay consent and redaction policy resolve to allow. It has no server SDK or implicit analytics-consent fallback. | Flags, errors, and APM signals |
| Error tracking | Sentry | Browser/server exception events, release/environment tags, source-map upload, and the error-issue workflow. Provisioning credentials remain build/provider-only. | Performance transactions, profiles, replay, logs, metrics, and feature flags |
| APM traces, metrics, and logs | SigNoz | Applications use OpenTelemetry SDKs and standard OTLP configuration through the in-graph collector. SigNoz receives those signals as the OTLP backend. | Product analytics, replay, feature flags, and the Sentry error-issue contract |
| APM traces, metrics, and logs | SigNoz | Applications use OpenTelemetry SDKs and export traces and metrics over OTLP/gRPC to the HTTPS operations intake, whose address the environment's `telemetry:` declaration delivers as the standard `OTEL_EXPORTER_OTLP_ENDPOINT` variable (or delivers nothing, and then nothing is exported); logs go to stdout. SigNoz receives those signals as the OTLP backend. | Product analytics, replay, feature flags, and the Sentry error-issue contract |

Provider manifests are allowlists. `provider-posthog` may project only
`product-analytics@1`; its browser initialization must disable flag remote
Expand All @@ -111,8 +111,9 @@ Sentry trace sampling at zero and installs no Sentry tracing integration.
`provider-signoz`, if API qualification succeeds, may manage exactly owned
dashboards and alerts but projects no application runtime configuration. In
particular, dashboard provisioning is not an application telemetry contract:
application OTLP endpoints remain instrumentation configuration resolved
through the telemetry service.
the application OTLP endpoint remains instrumentation configuration, delivered
as the standard `OTEL_EXPORTER_OTLP_ENDPOINT` variable through the
environment's optional `telemetry:` declaration.

The starter keeps the capability configurations independent. Selecting
PostHog never selects flags, errors, or observability; selecting Sentry never
Expand Down Expand Up @@ -687,7 +688,7 @@ names the source repository and a package version rather than a path:
modules:
- name: saas-starter
source: codefly-dev/module-saas-starter
version: "0.1.0"
version: "0.2.0"
```

Resolution fails closed, so the workspace must also say who it trusts to have
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ not this list, is the enumeration.

Beyond the API, the module ships the authenticated product frontend (whose
routes and navigation modules contribute to), a separately deployable public
marketing site, and the cache, store, vault, telemetry, and gateway services
marketing site, and the cache, store, vault, and gateway services
the above runs on.

## What it does not own
Expand Down
4 changes: 2 additions & 2 deletions RELEASE_GATES.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Agent-generated `module/services/*/builder/Dockerfile` recipes must **not** be
configured in Dependabot: agents replace them before building. The coverage gate
rejects those entries. `scripts/ci/build-images.json` records the expected build
images and the owning agent source for Go,
Next.js and the Postgres migration builder (including telemetry's generated Go
Next.js and the Postgres migration builder (including the Go services' generated
recipe, which is not checked in).

The weekly `build-images.yml` monitor compares registry digests for the effective
Expand Down Expand Up @@ -448,7 +448,7 @@ reverse, fails the `release-contract` job.
| `scoped-pools` | the authority of the pools the store's logins reach: the scoped reader, the scoped writer and the request pool, judged against a native PostgreSQL the suite provisions and widens one grant at a time | `python3 scripts/qualify-scoped-pools.py --postgres-bin "$(pg_config --bindir)"`, which runs `go test -race ./qualification/scopedpools` and fails unless every declared test in that package ran and passed |

Two of those `go test ./...` invocations are worth reading carefully. This
repository holds **six independent Go modules** — root, `module/tools`, and one
repository holds **independent Go modules** — root, `module/tools`, and one
per Go service — with no `go.work`, so `go test ./...` covers only the module it
is run in. The `sdk-boundary` invocation runs in the root module (the module
agent, the host, the generated reference composition) and the `module-package`
Expand Down
6 changes: 0 additions & 6 deletions configurations/local-dogfood/observability.env.example

This file was deleted.

3 changes: 0 additions & 3 deletions configurations/local-dogfood/observability.secret.env.example

This file was deleted.

1 change: 0 additions & 1 deletion configurations/local/observability.env

This file was deleted.

9 changes: 3 additions & 6 deletions gitops.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,9 @@ type topologyModule struct {
}

type topologyInterface struct {
Service string `yaml:"service"`
Endpoint string `yaml:"endpoint"`
Visibility string `yaml:"visibility"`
AllowModules []string `yaml:"allow-modules,omitempty"`
Service string `yaml:"service"`
Endpoint string `yaml:"endpoint"`
Visibility string `yaml:"visibility"`
}

type topologyService struct {
Expand Down Expand Up @@ -2474,7 +2473,6 @@ func bootstrapJobIngressPolicy(namespace string, labels map[string]string, servi
"ingress": []any{map[string]any{
"from": []any{map[string]any{"podSelector": map[string]any{"matchLabels": map[string]string{
"codefly.dev/bootstrap-service": service,
"job-name": service,
}}}},
"ports": networkPorts(ports),
}},
Expand All @@ -2490,7 +2488,6 @@ func bootstrapJobEgressPolicy(namespace string, labels map[string]string, servic
Spec: map[string]any{
"podSelector": map[string]any{"matchLabels": map[string]string{
"codefly.dev/bootstrap-service": service,
"job-name": service,
}},
"policyTypes": []string{"Egress"},
"egress": []any{map[string]any{
Expand Down
3 changes: 0 additions & 3 deletions gitops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2365,9 +2365,6 @@ func serviceManifestFixture(name, endpoint, api, visibility string, port int, to
}
if visibility != "private" {
manifest.WriteString(" visibility: " + visibility + "\n")
if visibility == "internal" {
manifest.WriteString(" allow-modules: [\"*\"]\n")
}
}
manifest.WriteString("spec:\n")
manifest.WriteString(spec)
Expand Down
Loading
Loading