Prepare persistent personal app release and guarded OIDC repair
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
This commit is contained in:
parent
a1989f19db
commit
ac7bac1852
7 changed files with 164 additions and 36 deletions
17
.dockerignore
Normal file
17
.dockerignore
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
.git
|
||||
.venv
|
||||
.env
|
||||
.env.*
|
||||
.auth
|
||||
var
|
||||
staticfiles
|
||||
db.sqlite3
|
||||
**/__pycache__
|
||||
**/*.pyc
|
||||
.pytest_cache
|
||||
.ruff_cache
|
||||
scripts/node_modules
|
||||
tests
|
||||
docs
|
||||
history
|
||||
workplans
|
||||
|
|
@ -38,7 +38,8 @@ COPY manage.py pyproject.toml ./
|
|||
COPY coulomb_social ./coulomb_social
|
||||
COPY scripts/docker-entrypoint.sh /app/docker-entrypoint.sh
|
||||
|
||||
RUN chmod +x /app/docker-entrypoint.sh \
|
||||
RUN python manage.py collectstatic --noinput \
|
||||
&& chmod +x /app/docker-entrypoint.sh \
|
||||
&& chown -R appuser:appuser /app
|
||||
USER appuser
|
||||
|
||||
|
|
|
|||
|
|
@ -29,19 +29,13 @@ X-Verified-Oidc-Claims: {"iss","sub","tenant","principal_type","aud",...}
|
|||
plus `coulomb-social`. Trust is the proxy secret; claims were verified by
|
||||
KeyCape OIDC at the app edge.
|
||||
|
||||
### Operator: enable HTTP mode locally
|
||||
### Governed credential configuration
|
||||
|
||||
```bash
|
||||
# secret never printed to shell history if you use process substitution carefully
|
||||
export USER_ENGINE_BASE_URL=https://users.92-205-62-239.nip.io
|
||||
export USER_ENGINE_PROXY_SECRET="$(kubectl -n user-engine get secret user-engine-runtime \
|
||||
-o jsonpath='{.data.proxy-secret}' | base64 -d)"
|
||||
export USER_ENGINE_EXPECTED_AUDIENCE=user-engine-portal
|
||||
# then OIDC or dev-login
|
||||
```
|
||||
|
||||
OpenBao lane for the proxy secret (future): document under railiance-platform
|
||||
workload KV; until then kubectl-sourced secret is operator-only on the workstation.
|
||||
Live HTTP mode already uses mounted runtime credential references. Do not
|
||||
extract the proxy secret with kubectl/jsonpath or print it into shell/chat.
|
||||
For a new credential need, run `warden route find "user-engine trusted proxy credential" --json`
|
||||
and follow the owning OpenBao/platform lane. Interactive personal login belongs
|
||||
to KeyCape/NetKingdom; it does not require retrieving this server credential.
|
||||
|
||||
## Profile attributes (shell only)
|
||||
|
||||
|
|
|
|||
47
scripts/keycape-client-repair.py
Normal file
47
scripts/keycape-client-repair.py
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Restore the historical public client through NetKingdom's guarded lane.
|
||||
|
||||
Inspection is read-only. Apply requires exact founder approval and a fresh
|
||||
UID/resource-version receipt. Secret values stay inside the owner helper.
|
||||
"""
|
||||
import importlib.util
|
||||
import os
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
def load(name, path):
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
result = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(result)
|
||||
return result
|
||||
|
||||
|
||||
def configure(owner_root):
|
||||
rollout = load("keycape_guarded_rollout", owner_root / "portal-client-rollout.py")
|
||||
historical = load("coulomb_registration", owner_root / "register-coulomb-social.py")
|
||||
original = rollout.replacement
|
||||
rollout.portal = SimpleNamespace(CLIENT_ID=historical.CLIENT_ID, CLIENT=historical.CLIENT)
|
||||
|
||||
def replacement(secret):
|
||||
_, config, _ = rollout.pin.issuer_document(secret)
|
||||
for client in config.get("clients", []):
|
||||
if client.get("clientId") == historical.CLIENT_ID:
|
||||
rollout.require(client == historical.CLIENT, "existing_registration_differs")
|
||||
return original(secret)
|
||||
|
||||
rollout.replacement = replacement
|
||||
return rollout
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
owner_root = Path(os.environ.get(
|
||||
"NET_KINGDOM_KEYCAPE_DIR",
|
||||
str(Path.home() / "net-kingdom/sso-mfa/k8s/keycape"),
|
||||
))
|
||||
helper = configure(owner_root)
|
||||
except Exception:
|
||||
print('{"status":"failed","reason":"owner_helper_unavailable"}')
|
||||
raise SystemExit(1)
|
||||
raise SystemExit(helper.main())
|
||||
|
|
@ -1,26 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
# Register this app's OIDC client on live KeyCape (kc.coulomb.social).
|
||||
# Delegates to net-kingdom/sso-mfa/k8s/keycape/register-coulomb-social.sh
|
||||
# Inspect by default; explicit dry-run/apply use guarded owner receipts.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
NK_SCRIPT="${NET_KINGDOM_KEYCAPE_DIR:-$HOME/net-kingdom/sso-mfa/k8s/keycape}/register-coulomb-social.sh"
|
||||
|
||||
if [[ ! -x "$NK_SCRIPT" && ! -f "$NK_SCRIPT" ]]; then
|
||||
echo "ERROR: KeyCape register script not found: $NK_SCRIPT" >&2
|
||||
echo "Clone net-kingdom or set NET_KINGDOM_KEYCAPE_DIR." >&2
|
||||
exit 1
|
||||
if [[ $# -eq 0 ]]; then
|
||||
set -- inspect
|
||||
fi
|
||||
|
||||
chmod +x "$NK_SCRIPT" 2>/dev/null || true
|
||||
bash "$NK_SCRIPT"
|
||||
|
||||
echo ""
|
||||
echo "Next: export OIDC settings and restart the app:"
|
||||
echo " export OIDC_ENABLED=true"
|
||||
echo " export OIDC_ISSUER=https://kc.coulomb.social"
|
||||
echo " export OIDC_CLIENT_ID=coulomb-social"
|
||||
echo " export OIDC_REDIRECT_URI=http://127.0.0.1:8008/auth/callback/"
|
||||
echo " # no client secret — public + PKCE"
|
||||
echo " make run"
|
||||
echo "Docs: $ROOT/docs/identity/oidc-client.md"
|
||||
exec python3 "$ROOT/scripts/keycape-client-repair.py" "$@"
|
||||
|
|
|
|||
49
scripts/test_keycape_client_repair.py
Normal file
49
scripts/test_keycape_client_repair.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
"""Synthetic owner-lane checks; run with python3 scripts/test_keycape_client_repair.py."""
|
||||
import base64
|
||||
import json
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
import yaml
|
||||
|
||||
from importlib.machinery import SourceFileLoader
|
||||
|
||||
adapter = SourceFileLoader("csoc_repair", str(Path(__file__).with_name("keycape-client-repair.py"))).load_module()
|
||||
|
||||
|
||||
class RepairTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.rollout = adapter.configure(Path.home() / "net-kingdom/sso-mfa/k8s/keycape")
|
||||
|
||||
def fixture(self, clients):
|
||||
raw = ("# keep comment\nauthelia:\n issuer: https://auth.example.invalid\n"
|
||||
" clientSecret: synthetic-marker\nclients:\n" +
|
||||
yaml.safe_dump(json.loads(json.dumps(clients)), sort_keys=False) + "tokenLifetime: 15m\n")
|
||||
return {"data": {"config.yaml": base64.b64encode(raw.encode()).decode(),
|
||||
"key.pem": "synthetic-key"}}, raw
|
||||
|
||||
def test_insert_preserves_bytes_and_is_idempotent(self):
|
||||
secret, raw = self.fixture([{"clientId": "existing", "clientType": "public"}])
|
||||
encoded, changed = self.rollout.replacement(secret)
|
||||
updated = base64.b64decode(encoded).decode()
|
||||
self.assertTrue(changed)
|
||||
self.assertTrue(updated.startswith(raw[:raw.index("tokenLifetime:")]))
|
||||
self.assertTrue(updated.endswith("tokenLifetime: 15m\n"))
|
||||
expected = yaml.safe_load(raw)
|
||||
expected["clients"].append(self.rollout.portal.CLIENT)
|
||||
self.assertEqual(yaml.safe_load(updated), expected)
|
||||
self.assertEqual(secret["data"]["key.pem"], "synthetic-key")
|
||||
secret["data"]["config.yaml"] = encoded
|
||||
self.assertEqual(self.rollout.replacement(secret), (encoded, False))
|
||||
|
||||
def test_refuses_different_or_duplicate_registration(self):
|
||||
client = self.rollout.portal.CLIENT
|
||||
for clients in [[dict(client, redirectUris=["https://other.invalid/callback"])],
|
||||
[dict(client, allowedScopes=["openid", "admin"])],
|
||||
[client, client]]:
|
||||
with self.subTest(clients=clients), self.assertRaises(self.rollout.Refused):
|
||||
self.rollout.replacement(self.fixture(clients)[0])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -66,7 +66,7 @@ an instruction to bulk-move every space before the first user review.
|
|||
|
||||
```task
|
||||
id: CSOC-WP-0008-T01
|
||||
status: wait
|
||||
status: progress
|
||||
priority: high
|
||||
state_hub_task_id: "6adce69f-9011-5ada-a920-b2228aa15218"
|
||||
```
|
||||
|
|
@ -266,3 +266,41 @@ clipboard and blocked/manual fallback pass Chromium checks with synthetic data.
|
|||
Full application suite: 87 passed; new test Ruff clean. Real latest protocol
|
||||
reconciliation and actual mail-client/user review remain T03/T09, not completed
|
||||
by these tests. No live deploy, private-data import or mail sending performed.
|
||||
|
||||
## Live orientation and personal account — 2026-10-06
|
||||
|
||||
Fresh checks confirm a healthy 1/1 coulomb-social Helm workload on railiance01
|
||||
(92.205.62.239), image 7fcd0cf, revision 9. app.coulomb.social landing and health
|
||||
return 200; KeyCape discovery is live. No content PVC/CONTENT_ROOT exists in
|
||||
that old release. One live Member links the user-selected tegwick identity to
|
||||
KeyCape and tenant:coulomb; one demo space exists. No new password/account is
|
||||
needed. The user tried sign-in and received invalid_profile_usage / unknown
|
||||
client_id. Guarded issuer inspection confirms the coulomb-social client is absent;
|
||||
the stored Member and healthy discovery did not prove interactive login worked.
|
||||
|
||||
T01 now progresses by preparing the latest tested app image with collected
|
||||
static assets and an owning-chart persistent CONTENT_ROOT upgrade. Single-writer
|
||||
Recreate avoids concurrent filesystem writers and rolling CPU surge. Exact live
|
||||
change approval follows the prepared diff/dry-run and immutable image receipt.
|
||||
Node CPU requests observed 3455m/4000m; disk has 123G available.
|
||||
No deployment or credential change was made by these read-only checks.
|
||||
|
||||
## T11 — Restore personal OIDC sign-in
|
||||
|
||||
```task
|
||||
id: CSOC-WP-0008-T11
|
||||
status: progress
|
||||
priority: high
|
||||
```
|
||||
|
||||
Restore the historical NetKingdom public coulomb-social authorization-code/PKCE
|
||||
client through the owning guarded helper; refuse differing existing registrations,
|
||||
preserve unrelated configuration bytes and Secret data, pin cluster identity and
|
||||
Secret UID/resourceVersion. Inspection and server dry-run passed on 2026-10-06;
|
||||
no live change made. Existing historical ordinary AAL1 behavior (mfaRequired:
|
||||
false) is explicit in the review packet; shared issuer restart requires exact
|
||||
founder approval. User tegwick must then confirm interactive login. Do not mark
|
||||
this task done on an HTTP redirect or discovery-only check.
|
||||
|
||||
Knowledge receipt: emergent-security 0.2.6 identity, verified-files,
|
||||
orientation-only; digest 8d1d6a9d4d07fec7b619618de7dfe2be2254c1790f85f4198c7fe19db9751c02.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue