You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Folds all pending work into the unreleased 1.0.0 cut so every published package
ships at 1.0.0: the three pending changesets are folded into each package's curated
[1.0.0] CHANGELOG and removed, and .changeset/config.json gains
onlyUpdatePeerDependentsWhenOutOfRange so a future core minor no longer force-majors
the satellites through their peer ranges.
README & package-docs red team
- Corrected the sso/billing/backup/websockets README stability badges from
experimental to release candidate (they contradicted docs/reference/stability.md);
split the core/root blockquote so the satellite *packages* read release candidate
and only the in-core opt-in features stay experimental.
- Configure-first install for billing/backup/sso; per-package corrections: sso
migration ownership (the package owns tenant_sso_configs; migration:run
--connection=backoffice), backup required @adonisjs/queue peer + backup_encryption
doctor check + commands table, billing Configuration section, websockets
onTenantEvent handler rule.
- New packages/reporting/README.md (the only satellite without one).
- core/root highlight counts corrected to match the code (28 typed events, 39 admin
endpoints, nine doctor checks), test-count badge softened to non-numeric, and the
reference-app/contributing snippets point at the real examples/api/docker-compose.yml.
- Fixed adjacent doc bugs surfaced in review: a nonexistent compose.test.yml
reference, broken core examples/api/ relative links, and a backup docs flag table
documenting a nonexistent tenant:clone --dest.
CI guards (so the above can't silently drift again)
- check-stability-versions.mjs now also asserts each README badge mirrors the matrix.
- New scripts/check-readme-links.mjs (relative + docs-site links resolve) and
scripts/check-readme-counts.mjs (doctor=9 / admin endpoints=39 / events=28 pinned to
source), wired into the lint-and-typecheck CI job.
Admin audit attribution
- Every mutating admin action (REST, the matching ace commands, and custom actions)
writes an attributed, append-only admin:<resource>:<verb> audit row sourced from
resolveAdminActor — never the request body, never a secret; best-effort, never fails
the operation it records. Lifecycle commands gain an optional --admin=<id> flag
(absent records the row as system).
- Deleting a non-existent webhook/feature flag now returns 404; an empty webhook PUT
and disabling an already-disabled SSO config short-circuit with unchanged:true and
write no row; admin OpenAPI info.version mirrors package.json; the admin sso peer is
marked optional in the manifest.
Also folds the metrics-bundle fix (configure --with=metrics now publishes all three
metrics tables) into the core [1.0.0] changelog.
Gates: stability/links/counts/doc-paths/positioning/graduation/lockfile, lint, and
test:integrity all green. docs:build was validated earlier in this work and is not
re-run here (local memory ceiling); its dead-link gate is unaffected by these
link-neutral doc edits.
Copy file name to clipboardExpand all lines: README.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# @adonisjs-lasagna/saas-tenancy
2
2
3
3
<palign="center">
4
-
<imgsrc="assets/hero.webp"alt="Lasagna — SaaS multi-tenancy for AdonisJS 7. Every tenant lives in its own isolated PostgreSQL schema. Around it: connection routing, circuit breaking, queues, contextual logging, plans and quotas, scheduled backups with retention, read-replica routing, soft delete, and a satellite suite covering audit logs, webhooks, branding, SSO, feature flags, metrics, and Stripe billing."width="100%" />
4
+
<imgsrc="assets/hero.webp"alt="Lasagna — SaaS multi-tenancy for AdonisJS 7. Every tenant lives in its own isolated PostgreSQL schema. Around it: connection routing, circuit breaking, queues, contextual logging, plans and quotas, scheduled backups with retention, read-replica routing, soft delete, and a satellite suite covering audit logs, webhooks, branding, SSO, feature flags, metrics, and multi-provider billing (Stripe, Paddle, Lemon Squeezy)."width="100%" />
> **Stability: release candidate.** The isolation core is feature complete and green in CI against real Postgres and Redis, but the `stable` label is withheld until an independent security review and production mileage close. The satellites (billing, SSO, admin, backup, and the opt-in in-core features like quotas, webhooks, and metrics) are **experimental**. Full breakdown and the 1.x semver promise in the [stability matrix](https://arcoders.github.io/Adonisjs-lasagna-saas-tenancy/reference/stability).
19
+
> **Stability: release candidate.** The isolation core is feature complete and green in CI against real Postgres and Redis, but the `stable` label is withheld until an independent security review and production mileage close. The satellite **packages** (admin, SSO, billing, backup, websockets, reporting) are **release candidate** too; the opt-in in-core features (quotas, webhooks, metrics, audit logs, branding, feature flags, impersonation) are **experimental**. Full breakdown and the 1.x semver promise in the [stability matrix](https://arcoders.github.io/Adonisjs-lasagna-saas-tenancy/reference/stability).
20
20
21
21
I built this because the AdonisJS ecosystem deserved a proper multi
22
22
tenancy foundation, and because every SaaS I touched eventually outgrew
@@ -38,16 +38,16 @@ and runs the full e2e suite against it.
38
38
|**Schema isolation**| Each tenant gets its own `tenant_<uuid>` PostgreSQL schema, provisioned and routed automatically. |
39
39
|**Circuit breaker**| Opossum wraps every tenant DB call; OPEN state is restored from Redis on restart so a known-down tenant DB fails fast across deploys. One bad schema can't take down the others. |
40
40
|**Dependency resilience**| Per-dependency fail-open/fail-closed degradation policy via `ResilienceService`. Emits `DependencyDegraded` for alerting and returns a typed 503 (`DependencyUnavailableException`) when fail-closed. |
|**Contextual logging**|`tenantId` rides along through HTTP and queue jobs via `AsyncLocalStorage`. |
43
-
|**`tenant:doctor`**|Ten built-in checks, `--fix` for auto-recovery, `--json` for CI, `--watch` for a live TUI. |
43
+
|**`tenant:doctor`**|Nine built-in checks (plus `backup_recency` and `backup_encryption` when the backup satellite is installed), `--fix` for auto-recovery, `--json` for CI, `--watch` for a live TUI. |
44
44
|**Plans and quotas**| Declarative plans, rolling counters, snapshot usage, an `enforceQuota()` middleware that returns 429 and emits `TenantQuotaExceeded`. |
45
45
|**Scheduled backups + retention**| Tier-based intervals and `keepLast`, S3 mirror with purge awareness, idempotent cron command. |
0 commit comments