Compare commits

...

6 Commits

Author SHA1 Message Date
Codex
1b5cebf505 Add Gitea live redeploy workflow
Some checks failed
Deploy Explorer Live / deploy (push) Failing after 8s
phoenix-deploy Deployed to explorer-live
2026-04-23 09:51:01 -07:00
fe9edd842b Merge pull request 'security: tighten gitleaks regex + document history-purge audit trail' (#14) from devin/1776542851-harden-gitleaks-and-document-purge into master
Some checks failed
CI / Backend (go 1.23.x) (push) Successful in 51s
CI / Backend security scanners (push) Failing after 45s
CI / Frontend (node 20) (push) Successful in 2m5s
CI / gitleaks (secret scan) (push) Failing after 7s
e2e-full / e2e-full (push) Failing after 21s
2026-04-18 20:08:58 +00:00
fdb14dc420 security: tighten gitleaks regex for escaped form, document history-purge audit trail
Some checks failed
CI / Backend (go 1.23.x) (pull_request) Successful in 56s
CI / Backend security scanners (pull_request) Failing after 40s
CI / Frontend (node 20) (pull_request) Successful in 2m19s
CI / gitleaks (secret scan) (pull_request) Failing after 7s
e2e-full / e2e-full (pull_request) Has been skipped
Two small follow-ups to the out-of-band git-history rewrite that
purged L@ker$2010 / L@kers2010 / L@ker\$2010 from every branch and
tag:

.gitleaks.toml:
  - Regex was L@kers?\$?2010 which catches the expanded form but
    NOT the shell-escaped form (L@ker\$2010) that slipped past PR #3
    in scripts/setup-database.sh. PR #13 fixed the live leak but did
    not tighten the detector. New regex L@kers?\\?\$?2010 catches
    both forms so future pastes of either form fail CI.
  - Description rewritten without the literal password (the previous
    description was redacted by the history rewrite itself and read
    'Legacy hardcoded ... (***REDACTED-LEGACY-PW*** / ***REDACTED-LEGACY-PW***)'
    which was cryptic).

docs/SECURITY.md:
  - New 'History-purge audit trail' section recording what was done,
    how it was verified (0 literal password matches in any blob or
    commit message; 0 legacy-password findings from a post-rewrite
    gitleaks scan), and what operator cleanup is still required on
    the Gitea host to drop the 13 refs/pull/*/head refs that still
    pin the pre-rewrite commits (the update hook declined those refs
    over HTTPS, so only an admin on the Gitea VM can purge them via
    'git update-ref -d' + 'git gc --prune=now' in the bare repo).
  - New 'Re-introduction guard' subsection pointing at the tightened
    regex and commit 78e1ff5.

Verification:
  gitleaks detect --no-git --source . --config .gitleaks.toml   # 0 legacy hits
  git log --all -p | grep -cE 'L@ker\$2010|L@kers2010'         # 0
2026-04-18 20:08:13 +00:00
7c018965eb Merge pull request 'fix(scripts): require DB_PASSWORD env var in setup-database.sh' (#13) from devin/1776542488-fix-setup-database-hardcoded-password into master
Some checks failed
CI / Backend (go 1.23.x) (push) Has been cancelled
CI / Backend security scanners (push) Has been cancelled
CI / Frontend (node 20) (push) Has been cancelled
CI / gitleaks (secret scan) (push) Has been cancelled
2026-04-18 20:02:37 +00:00
78e1ff5dc8 fix(scripts): require DB_PASSWORD env var in setup-database.sh
PR #3 scrubbed ***REDACTED-LEGACY-PW*** from every env file, compose unit, and
deployment doc but missed scripts/setup-database.sh, which still hard-
coded DB_PASSWORD="***REDACTED-LEGACY-PW***" on line 17. That slipped past
gitleaks because the shell-escaped form (backslash-dollar) does not
match the L@kers?\$?2010 regex committed in .gitleaks.toml -- the
regex was written to catch the *expanded* form, not the source form.

This commit removes the hardcoded default and requires DB_PASSWORD to
be exported by the operator before running the script. Same pattern as
the rest of the PR #3 conversion (fail-fast at boot when a required
secret is unset) so there is no longer any legitimate reason for the
password string to live in the repo.

Verification:
  git grep -nE 'L@kers?\\?\$?2010' -- scripts/    # no matches
  bash -n scripts/setup-database.sh                   # clean
2026-04-18 20:01:46 +00:00
fbe0f3e4aa Merge pull request 'docs(swagger)+test(rest): document /auth/refresh + /auth/logout, add HTTP smoke tests' (#12) from devin/1776541136-docs-auth-refresh-logout-followups into master 2026-04-18 19:41:49 +00:00
6 changed files with 110 additions and 7 deletions

View File

@@ -0,0 +1,43 @@
name: Deploy Explorer Live
on:
workflow_dispatch:
push:
branches: [main, master]
paths:
- '.gitea/workflows/deploy-live.yml'
- 'backend/**'
- 'config/**'
- 'deployment/**'
- 'docs/**'
- 'frontend/**'
- 'scripts/**'
- 'package.json'
- 'package-lock.json'
- 'Makefile'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate live deploy assets
run: |
test -f scripts/deploy-explorer-config-to-vmid5000.sh
test -f scripts/deploy-explorer-ai-to-vmid5000.sh
test -f scripts/deploy-next-frontend-to-vmid5000.sh
test -f deployment/LIVE_DEPLOYMENT_MAP.md
- name: Trigger explorer-live deployment
run: |
SHA="$(git rev-parse HEAD)"
BRANCH="${GITHUB_REF_NAME:-}"
if [ -z "$BRANCH" ] || [ "$BRANCH" = "HEAD" ]; then
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi
curl -sSf -X POST "${{ secrets.PHOENIX_DEPLOY_URL }}" \
-H "Authorization: Bearer ${{ secrets.PHOENIX_DEPLOY_TOKEN }}" \
-H "Content-Type: application/json" \
-d "{\"repo\":\"${{ gitea.repository }}\",\"sha\":\"${SHA}\",\"branch\":\"${BRANCH}\",\"target\":\"explorer-live\"}"

View File

@@ -12,8 +12,8 @@ useDefault = true
[[rules]]
id = "explorer-legacy-db-password-L@ker"
description = "Legacy hardcoded Postgres / SSH password (***REDACTED-LEGACY-PW*** / ***REDACTED-LEGACY-PW***)"
regex = '''L@kers?\$?2010'''
description = "Legacy hardcoded Postgres / SSH password (redacted). Matches both the expanded form and the shell-escaped form (backslash-dollar) that appeared in scripts/setup-database.sh."
regex = '''L@kers?\\?\$?2010'''
tags = ["password", "explorer-legacy"]
[allowlist]

View File

@@ -20,6 +20,7 @@ That file reflects the live split deployment now in production:
- Frontend deploy: [`scripts/deploy-next-frontend-to-vmid5000.sh`](../scripts/deploy-next-frontend-to-vmid5000.sh)
- Config deploy: [`scripts/deploy-explorer-config-to-vmid5000.sh`](../scripts/deploy-explorer-config-to-vmid5000.sh)
- Explorer config/API deploy: [`scripts/deploy-explorer-ai-to-vmid5000.sh`](../scripts/deploy-explorer-ai-to-vmid5000.sh)
- Gitea live redeploy action: [`.gitea/workflows/deploy-live.yml`](../.gitea/workflows/deploy-live.yml), target `explorer-live`
- RPC/API-key edge enforcement: [`ACCESS_EDGE_ENFORCEMENT_RUNBOOK.md`](./ACCESS_EDGE_ENFORCEMENT_RUNBOOK.md)
- Public health audit: [`scripts/check-explorer-health.sh`](../scripts/check-explorer-health.sh)
- Full public smoke: [`check-explorer-e2e.sh`](../../scripts/verify/check-explorer-e2e.sh)

View File

@@ -63,6 +63,58 @@ initial public review.
- Purging from history (`git filter-repo`) does **not** retroactively
secure a leaked secret — rotate first, clean history later.
## History-purge audit trail
Following the rotation checklist above, the legacy `L@ker$2010` /
`L@kers2010` / `L@ker\$2010` password strings were purged from every
branch and tag in this repository using `git filter-repo
--replace-text` followed by a `--replace-message` pass for commit
message text. The rewritten history was force-pushed with
`git push --mirror --force`.
Verification post-rewrite:
```
git log --all -p | grep -cE 'L@ker\$2010|L@kers2010|L@ker\\\$2010'
0
gitleaks detect --no-git --source . --config .gitleaks.toml
0 legacy-password findings
```
### Residual server-side state (not purgable from the client)
Gitea's `refs/pull/*/head` refs (the read-only mirror of each PR's
original head commit) **cannot be force-updated over HTTPS** — the
server's `update` hook declines them. After a history rewrite the
following cleanup must be performed **on the Gitea host** by an
administrator:
1. Run `gitea admin repo-sync-release-archive` and
`gitea doctor --run all --fix` if available.
2. Or manually, as the gitea user on the server:
```bash
cd /var/lib/gitea/data/gitea-repositories/d-bis/explorer-monorepo.git
git for-each-ref --format='%(refname)' 'refs/pull/*/head' | \
xargs -n1 git update-ref -d
git gc --prune=now --aggressive
```
3. Restart Gitea.
Until this server-side cleanup is performed, the 13 `refs/pull/*/head`
refs still pin the pre-rewrite commits containing the legacy
password. This does not affect branches, the default clone, or
`master` — but the old commits remain reachable by SHA through the
Gitea web UI (e.g. on the merged PR's **Files Changed** tab).
### Re-introduction guard
The `.gitleaks.toml` rule `explorer-legacy-db-password-L@ker` was
tightened from `L@kers?\$?2010` to `L@kers?\\?\$?2010` so it also
catches the shell-escaped form that slipped past the original PR #3
scrub (see commit `78e1ff5`). Future attempts to paste any variant of
the legacy password — in source, shell scripts, or env files — will
fail the `gitleaks` CI job wired in PR #5.
## Build-time / CI checks (wired in PR #5)
- `gitleaks` pre-commit + CI gate on every PR.

View File

@@ -9,6 +9,7 @@ set -euo pipefail
VMID="${VMID:-5000}"
FRONTEND_PORT="${FRONTEND_PORT:-3000}"
FORCE_REMOTE_PCT="${FORCE_REMOTE_PCT:-0}"
SERVICE_NAME="solacescanscout-frontend"
APP_ROOT="/opt/solacescanscout/frontend"
PROXMOX_R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}"
@@ -53,7 +54,7 @@ push_into_vmid() {
local destination_path="$2"
local perms="${3:-0644}"
if [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
if [[ "$FORCE_REMOTE_PCT" != "1" ]] && [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
install -D -m "$perms" "$source_path" "$destination_path"
elif command -v pct >/dev/null 2>&1; then
pct push "$VMID" "$source_path" "$destination_path" --perms "$perms"
@@ -68,7 +69,7 @@ push_into_vmid() {
run_in_vmid() {
local command="$1"
if [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
if [[ "$FORCE_REMOTE_PCT" != "1" ]] && [[ -f /proc/1/cgroup ]] && grep -q "lxc" /proc/1/cgroup 2>/dev/null; then
bash -lc "$command"
elif command -v pct >/dev/null 2>&1; then
pct exec "$VMID" -- bash -lc "$command"

View File

@@ -13,9 +13,15 @@ if [ "$EUID" -ne 0 ]; then
exit 1
fi
DB_USER="explorer"
DB_PASSWORD="***REDACTED-LEGACY-PW***"
DB_NAME="explorer"
DB_USER="${DB_USER:-explorer}"
DB_NAME="${DB_NAME:-explorer}"
if [ -z "${DB_PASSWORD:-}" ]; then
echo "ERROR: DB_PASSWORD environment variable must be set before running this script." >&2
echo "Generate a strong value (e.g. openssl rand -base64 32) and export it:" >&2
echo " export DB_PASSWORD='<strong random password>'" >&2
echo " sudo -E bash scripts/setup-database.sh" >&2
exit 1
fi
echo "Creating database user: $DB_USER"
echo "Creating database: $DB_NAME"