diff --git a/JOURNAL.md b/JOURNAL.md index 8f6e5ae..e1cf981 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -4,7 +4,7 @@ **Project**: TSYSDevStack-SupportStack-Cloudron **Goal**: Package ~57 applications for Cloudron PaaS platform **Start Date**: 2025-01-24 -**Current Status**: 11/~57 packages completed (~19%) +**Current Status**: 12/~57 packages completed (~21%) ## Completed Packages @@ -893,6 +893,79 @@ traversal (frp/ngrok class, Rust); this package runs the **server** side **Commit**: `feat: add Rathole Cloudron package (Infrastructure) [#650]` +### 12. Database Gateway (Infrastructure) ✅ +**Date**: 2026-09-01 +**Application**: Database Gateway (dbgw) — policy-checked web gateway to +PostgreSQL databases (OIDC login, OPA-authorized queries, cached results) +**Package Size**: 93.7MB (alpine runtime; smallest package so far) +**Port**: 8080 (httpPort, single listener — web UI + LRPC API) +**Addons**: localstorage, postgresql (16) + +**Key Learnings**: +- **Auth gate verdict**: NATIVE OIDC, the preferred row — no local users, + no LDAP, the only login path is an OIDC provider. Perfect fit for the + Cloudron platform provider: `CLOUDRON_OIDC_ISSUER` / `CLIENT_ID` / + `CLIENT_SECRET` are written into `users.*` of the seeded config; + redirect URL derives from `CLOUDRON_APP_ORIGIN` + `/auth/callback`; + roles map from the `groups` claim (Cloudron `admins` → admin, + `users` → user). First package in the set to consume the platform + OIDC env vars end-to-end +- **cgo is load-bearing**: the SQL parser is a libpg_query cgo binding — + `CGO_ENABLED=0` fails to compile (`undefined: pg.Parse`). The binary + therefore links musl and will not exec on Ubuntu/glibc bases (fails + with a misleading "no such file or directory") → runtime base is + alpine:3.23, same as upstream's own image, with bash / jq / openssl / + postgresql16-client apk-installed for start.sh (the mirror image of the + Rathole glibc trap) +- **Config is a file, not env**: the app takes one JSON config (`-c`), + validated with required `role_mapping` and `policy.path`. start.sh + builds it with `jq -n --arg` on first run so secrets are escaped + safely into JSON, then admins edit `/app/data/config.json` (targets, + role mapping) and `/app/data/opa/simple.rego` (query policy) with the + Cloudron file manager; restart applies +- **Migrations**: goose SQL embedded in the binary; `migrate-up` subcommand + is run explicitly in start.sh (the app also self-migrates on `run` — + belt and suspenders, both idempotent) +- **Frontend is pre-embedded**: upstream commits `internal/facade/ui/dist` + (`go:embed`), so the Go build ships the web UI — no Node stage needed +- **Validate() quirks**: targets list may be empty (seed `[]`), but every + `tables[].table` must be schema-qualified (`public.foo`) and every + role_mapping value must be exactly `admin` or `user` + +**Build Process**: +- Upstream `kazhuravlev/database-gateway` v0.24.0 (GPL-3.0, Go 1.26.1) + built from the cloned repo (multi-stage pattern #2): golang:1.26-alpine + builder mirrors the upstream Dockerfile (CGO_ENABLED=1 + ldflags + version stamp) → alpine:3.23 runtime +- Logo: upstream `frontend/src/favicon-96x96.png` copied directly +- start.sh: psql wait loop on the postgresql addon → seed `.cookie_secret` + (openssl rand -hex 32), `opa/simple.rego` (admins-only default), + `config.json` (jq template) → `migrate-up` → `exec run` + +**Validation**: +- `docker build --cgroup-parent ukrrs-batch.slice -t + database-gateway-cloudron:test` → green +- `--version` smoke in the image → `gateway version v0.24.0` +- End-to-end vs a throwaway postgres:16-alpine on a docker network with + fake CLOUDRON_* env: PG wait loop, config + policy seeding, all 5 + goose migrations applied (bookmarks / query_results tables verified + with psql), rego policy compiled, gateway reached the OIDC discovery + step and failed only on the bogus issuer (expected off-Cloudron; the + real platform issuer resolves at install time) + +**Files Created**: +- Dockerfile (multi-stage Go, CGO, alpine:3.23 runtime) +- CloudronManifest.json (manifestVersion 2, httpPort 8080, localstorage + + postgresql 16) +- start.sh (DB wait, jq config seed, policy seed, migrate-up, exec) — + committed executable +- README.md (auth story, config guide, target walkthrough) +- CHANGELOG.md +- .env.example (Cloudron-provided env documented) +- logo.png (96x96, upstream favicon) + +**Commit**: `feat: add Database-Gateway Cloudron package (Infrastructure) [#639]` + --- ## Packaging Pattern: Download Pre-Compiled Binaries diff --git a/Package-Workspace/Infrastructure/database-gateway/.env.example b/Package-Workspace/Infrastructure/database-gateway/.env.example new file mode 100644 index 0000000..3b9abd9 --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/.env.example @@ -0,0 +1,30 @@ +# Environment knobs for the Database Gateway Cloudron package. +# +# The app itself is configured through /app/data/config.json (seeded on +# first start; see README.md). The variables below are consumed by +# start.sh at seed time and are provided automatically by Cloudron — +# do NOT set them by hand. + +# --- Cloudron platform OIDC provider (injected by Cloudron) ------------------- +# Written into users.* of /app/data/config.json on first start. +#CLOUDRON_OIDC_ISSUER=https://my.example.com/openid +#CLOUDRON_OIDC_CLIENT_ID= +#CLOUDRON_OIDC_CLIENT_SECRET= +#CLOUDRON_OIDC_TOKEN_SIGNATURE_ALGORITHM=RS256 + +# --- App origin (injected by Cloudron) ---------------------------------------- +# Redirect URL is derived as ${CLOUDRON_APP_ORIGIN}/auth/callback. +#CLOUDRON_APP_ORIGIN=https://dbgw.example.com + +# --- PostgreSQL addon (injected by Cloudron) ---------------------------------- +# Gateway storage: profiles, bookmarks, query results, migrations. +#CLOUDRON_POSTGRESQL_HOST= +#CLOUDRON_POSTGRESQL_PORT=5432 +#CLOUDRON_POSTGRESQL_DATABASE= +#CLOUDRON_POSTGRESQL_USERNAME= +#CLOUDRON_POSTGRESQL_PASSWORD= + +# --- Operator-editable files in /app/data ------------------------------------- +# config.json database targets + role mapping (restart after edit) +# opa/simple.rego query authorization policy (restart after edit) +# .cookie_secret session cookie secret (rotate = logout everyone) diff --git a/Package-Workspace/Infrastructure/database-gateway/CHANGELOG.md b/Package-Workspace/Infrastructure/database-gateway/CHANGELOG.md new file mode 100644 index 0000000..492e74b --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/CHANGELOG.md @@ -0,0 +1,18 @@ +# Changelog + +## [0.24.0] - 2026-09-01 + +Initial Cloudron package for +[Database Gateway](https://github.com/kazhuravlev/database-gateway) v0.24.0 +(ticket [#639](https://projects.knownelement.com/issues/639)). + +- Multi-stage Go build (golang:1.26-alpine → cloudron/base:3.2.0), frontend + embedded by upstream via `go:embed`. +- Native OIDC login wired to the Cloudron platform identity provider + (`CLOUDRON_OIDC_ISSUER` / `CLIENT_ID` / `CLIENT_SECRET`); roles mapped from + the `groups` claim (`admins` → admin, `users` → user). +- `postgresql` addon (16) for the gateway's own storage; migrations applied + on every start via `migrate-up`. +- `/app/data/config.json` + `/app/data/opa/simple.rego` seeded on first run; + operators add database targets and OPA policy rules via the file manager. +- Single HTTP listener on port 8080 (`httpPort`). diff --git a/Package-Workspace/Infrastructure/database-gateway/CloudronManifest.json b/Package-Workspace/Infrastructure/database-gateway/CloudronManifest.json new file mode 100644 index 0000000..74e0d2a --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/CloudronManifest.json @@ -0,0 +1,24 @@ +{ + "manifestVersion": 2, + "type": "app", + "id": "io.cloudron.dbgateway", + "title": "Database Gateway", + "description": "Web gateway for secure, policy-controlled access to PostgreSQL databases. Users authenticate via OIDC (Cloudron single sign-on) and run queries that are parsed and authorized by embedded OPA policies per user, target, operation and table. Query results are stored with shareable links for debugging and auditing.", + "author": "Kirill Zhuravlev", + "website": "https://github.com/kazhuravlev/database-gateway", + "contactEmail": "cloudron@tsys.dev", + "tagline": "Policy-checked SQL gateway for your databases", + "version": "0.24.0", + "healthCheckPath": "/", + "httpPort": 8080, + "memoryLimit": 512, + "addons": { + "localstorage": true, + "postgresql": { + "version": "16" + } + }, + "mediaLinks": [], + "changelog": "Initial Cloudron package for Database Gateway 0.24.0. Native OIDC login wired to the Cloudron platform identity provider (admins group -> gateway admin, users group -> gateway user); local PostgreSQL addon stores profiles, bookmarks and query results; OPA policies and database targets are configured from /app/data. Single HTTP listener on port 8080.", + "icon": "file://logo.png" +} diff --git a/Package-Workspace/Infrastructure/database-gateway/Dockerfile b/Package-Workspace/Infrastructure/database-gateway/Dockerfile new file mode 100644 index 0000000..14aed34 --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/Dockerfile @@ -0,0 +1,65 @@ +# Database Gateway Cloudron Package +# +# Database Gateway (dbgw) is a web gateway for secure, policy-controlled +# access to PostgreSQL databases: users log in via OIDC and every query is +# parsed and authorized by embedded OPA policies (per user, target, +# operation and table) before it reaches a remote database. Query results +# are stored in a local PostgreSQL storage with shareable links. +# +# Upstream: https://github.com/kazhuravlev/database-gateway (v0.24.0, Go 1.26, Echo) +# - Single Go binary; the frontend is already built and embedded in the +# repo (internal/facade/ui/dist via go:embed), so no Node stage needed +# - Listens on 0.0.0.0:8080; config file passed with `-c config.json` +# - Storage schema applied via the `migrate-up` subcommand (embedded SQL) +# +# Authentication: NATIVE OIDC (preferred). start.sh wires the Cloudron +# platform OIDC provider (CLOUDRON_OIDC_ISSUER / CLIENT_ID / CLIENT_SECRET) +# into /app/data/config.json on first run; roles map from the Cloudron +# `groups` claim (admins -> admin, users -> user). +# +# NOTE on base images: the SQL parser is a cgo binding (libpg_query), so the +# binary MUST be built with CGO_ENABLED=1 — a static CGO_ENABLED=0 build +# fails with `undefined: pg.Parse`. A musl-linked binary then needs a musl +# runtime, hence alpine:3.23 (same as upstream's own image) instead of the +# usual cloudron/base (Ubuntu/glibc). +FROM golang:1.26-alpine AS builder + +ARG VERSION=v0.24.0 + +WORKDIR /src + +# Mirrors the upstream Dockerfile build dependencies (git for module +# fetches, gcc/musl-dev for the CGO-enabled build). +RUN apk add --no-cache ca-certificates git gcc musl-dev + +# Cache dependency downloads separately from source changes. +COPY repo/go.mod repo/go.sum ./ +RUN go mod download + +COPY repo/ . +RUN CGO_ENABLED=1 go build \ + -ldflags "-s -w -X github.com/dev-services42/version.version=${VERSION}" \ + -o /out/database-gateway \ + ./cmd/gateway + +# Same runtime base as the upstream image. The tools back start.sh: +# bash (script), postgresql16-client (wait for the Cloudron PG addon), +# jq (seed config.json), openssl (cookie secret). +FROM alpine:3.23 + +RUN apk add --no-cache bash ca-certificates jq openssl postgresql16-client + +COPY --from=builder /out/database-gateway /usr/local/bin/database-gateway + +# start.sh waits for the postgresql addon, seeds /app/data/config.json and +# /app/data/opa/ on first run, applies migrations, then execs the gateway. +# Made executable on the host, not at build time (Cloudron builds hit +# permission errors on RUN chmod). +COPY start.sh /app/start.sh + +ENV WORKDIR=/app/data +WORKDIR ${WORKDIR} + +EXPOSE 8080 + +CMD ["/bin/bash", "/app/start.sh"] diff --git a/Package-Workspace/Infrastructure/database-gateway/README.md b/Package-Workspace/Infrastructure/database-gateway/README.md new file mode 100644 index 0000000..b6958f6 --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/README.md @@ -0,0 +1,85 @@ +# Database Gateway — Cloudron Package + +[Database Gateway](https://github.com/kazhuravlev/database-gateway) (dbgw) is +a web gateway for secure, controlled access to PostgreSQL databases: users +log in via OIDC and run SQL through a unified web UI, with every query +parsed and authorized by embedded **OPA policies** (per user, target, +operation and table). Results are stored in a local PostgreSQL with +shareable links for debugging and auditing. + +## Packaging overview + +| Aspect | Choice | +|--------|--------| +| Pattern | Multi-stage Go build (JOURNAL pattern #2) | +| Builder | `golang:1.26-alpine` (upstream's own build recipe, CGO on) | +| Base image | `alpine:3.23` (musl runtime required — see below) | +| Upstream | v0.24.0 (Go 1.26.1, Echo; frontend pre-built and embedded via `go:embed`) | +| Addons | `localstorage` + `postgresql` (16) — storage for profiles, bookmarks, query results | +| Auth | **Native OIDC (preferred)** wired to the Cloudron platform identity provider | +| Runtime | `start.sh` waits for Postgres, seeds config + OPA policy, `migrate-up`, execs `run` | + +Why alpine instead of `cloudron/base`: the SQL parser is a cgo binding +(libpg_query) — the binary must be built with `CGO_ENABLED=1` (a static +build fails with `undefined: pg.Parse`) and therefore links musl, which +does not exec on Ubuntu/glibc bases. Alpine runtime matches upstream's own +image; bash/psql/jq/openssl are apk-installed for `start.sh`. + +Why not the official image: upstream publishes `ghcr.io/kazhuravlev/ +database-gateway:latest` but tagging is `:latest`-only; building v0.24.0 +from the cloned source pins the version and lets the ldflags carry the +release tag into `/healthcheck`-style version output. + +## Authentication (auth gate verdict: OIDC, preferred) + +Database Gateway authenticates **only** via OIDC — no local user database, +no LDAP. This is the preferred row of the auth matrix: + +- `CLOUDRON_OIDC_ISSUER`, `CLOUDRON_OIDC_CLIENT_ID`, + `CLOUDRON_OIDC_CLIENT_SECRET` (injected by Cloudron's platform OIDC + provider, manifestVersion 2) are written into `/app/data/config.json` on + first start. +- Redirect URL: `${CLOUDRON_APP_ORIGIN}/auth/callback`. +- Scopes: `openid profile email groups`; `role_claim` is `groups`, mapped + `admins` → `admin`, `users` → `user` (Cloudron's built-in groups). +- Access policy is then enforced per query by OPA (see below), not just at + login. + +## Ports + +| Port | Type | Purpose | +|------|------|---------| +| 8080 | `httpPort` | Web UI + LRPC API (only listener) | + +## Configuration (persistent, in `/app/data`) + +- `config.json` — seeded once on first start (OIDC + storage from Cloudron + env). **Add your database targets here** with the Cloudron file manager; + restart the app after editing. See + [upstream example](https://github.com/kazhuravlev/database-gateway/blob/master/example/config.json) + for the full target format (connection, `default_schema`, + `tables[].table` must be schema-qualified, `fields` allowlist). +- `opa/simple.rego` — seeded default: Cloudron `admins` see all targets and + may run any op; everyone else denied until an operator extends the policy + (input subjects contain `user:` and `role:`). +- `.cookie_secret` — random 32-byte hex, generated once; rotating it + invalidates sessions. + +The **postgresql addon** database is the gateway's own storage (users, +bookmarks, cached results) — not a query target. Targets point at the +*other* PostgreSQL instances you want to reach. + +## Build & test + +```bash +docker build --cgroup-parent ukrrs-batch.slice -t database-gateway-cloudron:test Package-Workspace/Infrastructure/database-gateway/ +docker run --rm --entrypoint /usr/local/bin/database-gateway database-gateway-cloudron:test --version +``` + +## Files + +- `Dockerfile` — multi-stage Go build (golang:1.26-alpine → alpine:3.23, musl) +- `CloudronManifest.json` — manifestVersion 2, httpPort 8080, localstorage + postgresql addons +- `start.sh` — DB wait, config/policy seeding, migrations, exec gateway +- `.env.example` — environment knobs consumed at seed time +- `logo.png` — from upstream `frontend/src/favicon-96x96.png` diff --git a/Package-Workspace/Infrastructure/database-gateway/logo.png b/Package-Workspace/Infrastructure/database-gateway/logo.png new file mode 100644 index 0000000..38af8b5 Binary files /dev/null and b/Package-Workspace/Infrastructure/database-gateway/logo.png differ diff --git a/Package-Workspace/Infrastructure/database-gateway/start.sh b/Package-Workspace/Infrastructure/database-gateway/start.sh new file mode 100755 index 0000000..1569087 --- /dev/null +++ b/Package-Workspace/Infrastructure/database-gateway/start.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -euo pipefail + +# Database Gateway runtime setup: +# 1. wait for the Cloudron postgresql addon (storage for profiles/bookmarks/ +# query results) +# 2. seed /app/data/config.json + /app/data/opa/ on first run +# 3. apply the embedded schema migrations (migrate-up) +# 4. exec the gateway (web UI + LRPC API on 0.0.0.0:8080) + +CONFIG_PATH="/app/data/config.json" +OPA_DIR="/app/data/opa" +COOKIE_SECRET_PATH="/app/data/.cookie_secret" + +# --- 1. wait for PostgreSQL ------------------------------------------------- +DB_HOST=${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1} +DB_PORT=${CLOUDRON_POSTGRESQL_PORT:-5432} +DB_NAME=${CLOUDRON_POSTGRESQL_DATABASE:-dbgw} +DB_USER=${CLOUDRON_POSTGRESQL_USERNAME:-dbgw} +DB_PASSWORD=${CLOUDRON_POSTGRESQL_PASSWORD} + +echo "Waiting for PostgreSQL at ${DB_HOST}:${DB_PORT} ..." +until PGPASSWORD="${DB_PASSWORD}" psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" -c '\q' >/dev/null 2>&1; do + echo "PostgreSQL is unavailable - sleeping" + sleep 2 +done +echo "PostgreSQL is up" + +# --- 2. seed persistent configuration --------------------------------------- +# Persistent cookie secret (rotating it would invalidate live sessions). +if [[ ! -f "${COOKIE_SECRET_PATH}" ]]; then + umask 077 + openssl rand -hex 32 > "${COOKIE_SECRET_PATH}" + echo "Generated new cookie secret" +fi +COOKIE_SECRET=$(cat "${COOKIE_SECRET_PATH}") + +# Default OPA policy: Cloudron "admins" see every target and may run any op; +# everyone else is denied until an operator extends the policy. Edit with the +# Cloudron file manager; changes apply on restart. +mkdir -p "${OPA_DIR}" +if [[ ! -f "${OPA_DIR}/simple.rego" ]]; then + cat > "${OPA_DIR}/simple.rego" <<'EOF' +package gateway + +# Default Cloudron policy: the admins group is unrestricted; everyone else +# is denied until an operator edits this file (input.subjects contains +# user: and role: principals). +default allow_target := false +default allow_query := false + +allow_target if { + "role:admin" in input.subjects +} + +allow_query if { + "role:admin" in input.subjects +} +EOF + echo "Seeded default OPA policy at ${OPA_DIR}/simple.rego" +fi + +# Seed the app config once (jq handles escaping of secrets into JSON). OIDC +# comes from the Cloudron platform identity provider; targets (the databases +# this gateway may reach) are added by the operator by editing +# ${CONFIG_PATH} with the Cloudron file manager. +if [[ ! -f "${CONFIG_PATH}" ]]; then + jq -n \ + --arg db_host "${DB_HOST}" \ + --arg db_name "${DB_NAME}" \ + --arg db_user "${DB_USER}" \ + --arg db_password "${DB_PASSWORD}" \ + --argjson db_port "${DB_PORT}" \ + --arg issuer "${CLOUDRON_OIDC_ISSUER}" \ + --arg client_id "${CLOUDRON_OIDC_CLIENT_ID}" \ + --arg client_secret "${CLOUDRON_OIDC_CLIENT_SECRET}" \ + --arg origin "${CLOUDRON_APP_ORIGIN}" \ + --arg cookie_secret "${COOKIE_SECRET}" \ + --arg opa_dir "${OPA_DIR}" \ + '{ + targets: [], + users: { + client_id: $client_id, + client_secret: $client_secret, + issuer_url: $issuer, + redirect_url: ($origin + "/auth/callback"), + scopes: ["openid", "profile", "email", "groups"], + role_claim: "groups", + role_mapping: { + admins: "admin", + users: "user" + } + }, + policy: { path: $opa_dir }, + facade: { + port: 8080, + cookie_secret: $cookie_secret, + unsafe_cors_allow_all: false + }, + storage: { + host: $db_host, + port: $db_port, + database: $db_name, + username: $db_user, + password: $db_password, + use_ssl: false, + max_pool_size: 16 + } + }' > "${CONFIG_PATH}" + chmod 600 "${CONFIG_PATH}" + echo "Seeded config at ${CONFIG_PATH}" +fi + +# --- 3. migrations ----------------------------------------------------------- +echo "Applying database migrations ..." +/usr/local/bin/database-gateway -c "${CONFIG_PATH}" migrate-up + +# --- 4. run -------------------------------------------------------------------- +echo "Starting Database Gateway on :8080 ..." +exec /usr/local/bin/database-gateway -c "${CONFIG_PATH}" run diff --git a/README.md b/README.md index d41f8d3..57413cf 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ The Cloudron component focuses on packaging upstream free/libre/open application ### 📊 Current Progress - **Total Applications**: ~57 (see [GitUrlList.txt](GitUrlList.txt)) -- **Completed Packages**: 11/~57 (~19%) +- **Completed Packages**: 12/~57 (~21%) - **Packaging Templates**: Created ✅ -- **Packages Committed & Pushed**: 11 ✅ +- **Packages Committed & Pushed**: 12 ✅ - **Build Tickets**: 46 filed (#633-#678, umbrella [#632](https://projects.knownelement.com/issues/632), Redmine project 55); grist-core excluded (packaged upstream) @@ -33,6 +33,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application | 9 | Windmill | Automation | ~2GB | 8000 | localstorage, postgresql | ✅ Committed | | 10 | Easy-Gate | Infrastructure | 3.18GB | 8080 | localstorage (auth proxy) | ✅ Committed | | 11 | Rathole | Infrastructure | 3.51GB | 8000, 2333, 5200-5299 | localstorage (auth proxy) | ✅ Committed | +| 12 | Database Gateway | Infrastructure | 93.7MB | 8080 | localstorage, postgresql | ✅ Committed | ### 📦 Packages in Development @@ -66,7 +67,7 @@ None currently in development. ### ⚡ Productivity Metrics -- **Packages Completed**: 11/~57 (~19%) +- **Packages Completed**: 12/~57 (~21%) - **Average Package Time**: ~30 minutes - **Success Rate**: 100% (all packages built successfully) - **Commits Pushed**: 100% (all packages pushed to remote) @@ -91,7 +92,7 @@ Applications are organized by function rather than programming language: | **Documentation-Tools** | Documentation and diagramming tools | 3 | 1/3 (33%) | | **Financial-Payments** | Payment processing and financial infrastructure | 1 | 0/1 (0%) | | **Financial-Trading** | Trading and financial algorithm platforms | 1 | 0/1 (0%) | -| **Infrastructure** | Infrastructure and networking tools | 6 | 2/6 (33%) | +| **Infrastructure** | Infrastructure and networking tools | 6 | 3/6 (50%) | | **Legal** | Legal and compliance applications | 1 | 0/1 (0%) | | **Low-Code** | Low-code and no-code platforms | 3 | 1/3 (33%) | | **Monitoring** | Monitoring and observability tools | 6 | 1/6 (17%) | @@ -113,7 +114,7 @@ Applications are organized by function rather than programming language: | [DataHub](https://github.com/datahub-project/datahub) | [GitHub](https://github.com/datahub-project/datahub) | Modern data stack for end-to-end data management | Data-Management | | [Docassemble](https://github.com/jhpyle/docassemble) | [GitHub](https://github.com/jhpyle/docassemble) | Open-source expert system for guided interviews | Legal | | [Pimcore](https://github.com/pimcore/pimcore) | [GitHub](https://github.com/pimcore/pimcore) | Open-source digital experience platform | Business-Apps | -| [Database-Gateway](https://github.com/kazhuravlev/database-gateway) | [GitHub](https://github.com/kazhuravlev/database-gateway) | Database gateway and connection management | Infrastructure | +| [Database-Gateway](https://github.com/kazhuravlev/database-gateway) | [GitHub](https://github.com/kazhuravlev/database-gateway) | Database gateway and connection management | Infrastructure | ✅ Packaged | | [Webhook](https://github.com/adnanh/webhook) | [GitHub](https://github.com/adnanh/webhook) | Lightweight webhook receiver | API-Gateway | ✅ Packaged | | [FX](https://github.com/metrue/fx) | [GitHub](https://github.com/metrue/fx) | Function as a Service platform | DevOps-Tools | | [Fonoster](https://github.com/fonoster/fonoster) | [GitHub](https://github.com/fonoster/fonoster) | Open-source CPaaS for communications | Communication | diff --git a/STATUS.md b/STATUS.md index 78eabfc..558f28f 100644 --- a/STATUS.md +++ b/STATUS.md @@ -3,20 +3,20 @@ > **Human read-only. Agents maintain this file automatically after each work > session.** Do not edit by hand — the next agent run will overwrite it. > -> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — Rathole packaged -> (#650, Infrastructure, 11th package); auth gate verdict: no user concept, -> status page behind the Cloudron auth proxy, tunnels token-authenticated. +> **Last updated:** 2026-09-01 by Crush (GLM-5.2) — Database Gateway +> packaged (#639, Infrastructure, 12th package); auth gate verdict: native +> OIDC (preferred) — platform provider wired via CLOUDRON_OIDC_* env. ## Current State: STABLE (packaging phase, ongoing) -Cloudron packaging pipeline is operational. 11 of ~57 upstream applications are +Cloudron packaging pipeline is operational. 12 of ~57 upstream applications are packaged, committed, and pushed. Packaging templates exist for the core patterns. The gardening protocol (this file + AGENTS.md) keeps docs in sync. All remaining apps now carry build tickets (#633-#678) under umbrella [#632](https://projects.knownelement.com/issues/632) in Redmine project 55 — ready for the sequential grind-driver pattern. -## Completed Packages (11) +## Completed Packages (12) | # | Application | Category | Pattern | Port(s) | Addons | |---|-------------|----------|---------|---------|--------| @@ -31,6 +31,7 @@ ready for the sequential grind-driver pattern. | 9 | Windmill | Automation | Official-image wrapper + start.sh | 8000 | localstorage, postgresql | | 10 | Easy-Gate | Infrastructure | Multi-stage (Go) + auth proxy | 8080 | localstorage | | 11 | Rathole | Infrastructure | Pre-compiled binaries + auth proxy | 8000, 2333, 5200-5299 | localstorage | +| 12 | Database Gateway | Infrastructure | Multi-stage (Go, CGO) | 8080 | localstorage, postgresql | Each package lives in `Package-Workspace///` and contains a `Dockerfile`, `CloudronManifest.json`, `README.md`, `CHANGELOG.md`, `logo.png`, @@ -119,7 +120,7 @@ Full write-ups of each pattern + challenges are in [`JOURNAL.md`](JOURNAL.md). | DevOps-Tools | 1 | 0/1 | | | Financial-Payments | 1 | 0/1 | | | Financial-Trading | 1 | 0/1 | | -| Infrastructure | 6 | 2/6 | easy-gate, rathole done | +| Infrastructure | 6 | 3/6 | easy-gate, rathole, database-gateway done | | Legal | 1 | 0/1 | | | Project-Management | 1 | 0/1 | | | Scientific-Computing | 2 | 0/2 | | @@ -133,7 +134,7 @@ Auth capability is a hard gate before packaging (see LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only (unacceptable / blocked-on-auth). -### Completed packages (11) +### Completed packages (12) | App | OIDC | LDAP | Verdict | Note | |-----|------|------|---------|------| @@ -148,6 +149,7 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only | Windmill | yes | no | ✅ preferred | **Packaged**; OIDC configured via Admin Settings UI (no env vars) | | Easy-Gate | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` (no user concept; IP-subnet groups only) | | Rathole | n/a | n/a | 🔄 proxy | **Packaged** with `httpAuth.type=proxy` on the status page; tunnels secured by mandatory per-service tokens (Noise/TLS optional) | +| Database Gateway | yes | no | ✅ preferred | **Packaged**; native OIDC-only app — platform provider env (`CLOUDRON_OIDC_*`) seeded into config.json; roles from the `groups` claim | ### Candidates researched