Public-flip audit: generalize internal hosts/paths + drop Sulkta-internal refs
URLs, mount paths, and LAN host bindings parameterized via env or relative paths
so the repo stands up from a clean clone anywhere. Drop cross-codebase refs
("mirrors clawdforge's pattern"), Sulkta-Coop client/merchant test fixtures,
and audit-changelog scaffolding from comments. README terser, technical content
preserved.
This commit is contained in:
parent
8b1774130b
commit
b335405c02
23 changed files with 238 additions and 266 deletions
|
|
@ -1,6 +1,5 @@
|
|||
"""Bearer + IP allowlist authentication.
|
||||
|
||||
Mirrors clawdforge's pattern:
|
||||
- Bearer tokens hashed at rest (SHA-256). No plaintext stored.
|
||||
- Per-token IP allowlist (CIDR list). NULL means "any RFC1918 + loopback"
|
||||
via the global LAN allowlist.
|
||||
|
|
@ -9,8 +8,7 @@ Mirrors clawdforge's pattern:
|
|||
- Loopback always allowed (test client uses 127.0.0.1; FastAPI's
|
||||
`request.client.host` returns 'testclient' under TestClient and we patch
|
||||
that in tests).
|
||||
- Bearer tokens NEVER appear in error messages or log lines. Same hygiene
|
||||
as clawdforge.
|
||||
- Bearer tokens NEVER appear in error messages or log lines.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
"""SQLite ledger + migrations.
|
||||
|
||||
Why SQLite (not MariaDB like clawdforge): single-process, single-host service,
|
||||
no need for cross-host replication. The runner is the only writer; every
|
||||
HTTP worker reads. SQLite in WAL mode handles single-writer-many-readers
|
||||
cleanly. Trade-off documented in README.
|
||||
Why SQLite: single-process, single-host service, no cross-host replication
|
||||
needed. The runner is the only writer; every HTTP worker reads. SQLite in
|
||||
WAL mode handles single-writer-many-readers cleanly. Trade-off documented
|
||||
in README.
|
||||
|
||||
Why stdlib `sqlite3` + `run_in_executor` (not aiosqlite): one less dependency
|
||||
and the queries are tiny (fetchone / fetchall). The runner does its own log
|
||||
|
|
@ -13,7 +13,7 @@ Migration system:
|
|||
- Each entry in MIGRATIONS is (version_id, sql_text). Versions are date-tagged
|
||||
so they sort lexicographically.
|
||||
- Apply in order, INSERT OR IGNORE into schema_migrations to handle
|
||||
multi-worker boot races (mirrors cauldron's pattern).
|
||||
multi-worker boot races.
|
||||
- Migrations are append-only; never edit a landed migration, add a new one.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ Design notes:
|
|||
- Idempotency is enforced by a `digest_runs` table with UNIQUE(date, project_name).
|
||||
Calling run_once twice for the same date will only send one email per project.
|
||||
- SMTP send is done via stdlib smtplib (sync) wrapped in run_in_executor so
|
||||
we don't block the loop while postfix grumbles.
|
||||
we don't block the loop while the relay grumbles.
|
||||
- If SMTP isn't configured, the server lifespan logs a warning and skips
|
||||
scheduler startup. The /digests endpoints still work for dry-run rendering.
|
||||
- Patch-drafted / auto-patches / bugs.sulkta.com numbers are zero-state
|
||||
placeholders for v0.1 wave 2C — wave 3 / step 9 wires them.
|
||||
- Patch-drafted / auto-patches / external-tracker numbers are zero-state
|
||||
placeholders until the patch loop is wired up.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ class SmtpConfig:
|
|||
def _parse_pr_url(pr_url: str) -> tuple[str, str, int] | None:
|
||||
"""Pull (owner, repo, number) out of a Gitea-style PR URL.
|
||||
|
||||
Accepts URLs like ``http://192.168.0.5:3001/Sulkta-Coop/clawdforge/pulls/42``.
|
||||
Accepts URLs like ``http://git.example.com/org/repo/pulls/42``.
|
||||
Returns None if the URL doesn't look right — caller treats that as
|
||||
"can't determine state, assume open".
|
||||
"""
|
||||
|
|
@ -222,7 +222,7 @@ def _render_text(
|
|||
lines.append("")
|
||||
lines.append("Open follow-ups:")
|
||||
lines.append(f" - {open_followups} unmerged auto-patches")
|
||||
lines.append(" - 0 manual review tickets in bugs.sulkta.com")
|
||||
lines.append(" - 0 manual review tickets in external tracker")
|
||||
lines.append("")
|
||||
lines.append(f"Full log: {full_log_url}")
|
||||
return "\n".join(lines) + "\n"
|
||||
|
|
@ -283,7 +283,7 @@ tr td:first-child {{ font-size: 1.2em; }}
|
|||
<h3>Open follow-ups</h3>
|
||||
<ul>
|
||||
<li>{open_followups} unmerged auto-patches</li>
|
||||
<li>0 manual review tickets in bugs.sulkta.com</li>
|
||||
<li>0 manual review tickets in external tracker</li>
|
||||
</ul>
|
||||
<p class="foot">Full log: <a href="{full_log_url}">{full_log_url}</a></p>
|
||||
</body></html>
|
||||
|
|
@ -314,7 +314,7 @@ class DigestScheduler:
|
|||
time_zone: str = "America/Los_Angeles",
|
||||
hour: int = 6,
|
||||
minute: int = 0,
|
||||
full_log_base_url: str = "http://192.168.0.5:8810/digests",
|
||||
full_log_base_url: str = "http://localhost:8810/digests",
|
||||
gitea_pr_state_check=None,
|
||||
):
|
||||
self.db = db
|
||||
|
|
|
|||
|
|
@ -1056,16 +1056,21 @@ class Patcher:
|
|||
) -> bool:
|
||||
"""Commit the worktree changes to a new branch and push to origin.
|
||||
|
||||
Author is forced to ``Kayos <kayos@sulkta.com>``. We pass through
|
||||
--no-gpg-sign because crafting-table containers don't have signing
|
||||
keys; commit messages reference the finding id so the PR review
|
||||
can navigate back to the finding row in the API.
|
||||
Author defaults to ``crafting-table <crafting-table@localhost>``,
|
||||
overridable via ``CRAFTING_PATCHER_AUTHOR_NAME`` +
|
||||
``CRAFTING_PATCHER_AUTHOR_EMAIL``. We pass through --no-gpg-sign
|
||||
because crafting-table containers don't have signing keys; commit
|
||||
messages reference the finding id so the PR review can navigate
|
||||
back to the finding row in the API.
|
||||
"""
|
||||
import os
|
||||
author_name = os.environ.get("CRAFTING_PATCHER_AUTHOR_NAME", "crafting-table")
|
||||
author_email = os.environ.get("CRAFTING_PATCHER_AUTHOR_EMAIL", "crafting-table@localhost")
|
||||
env = {
|
||||
"GIT_AUTHOR_NAME": "Kayos",
|
||||
"GIT_AUTHOR_EMAIL": "kayos@sulkta.com",
|
||||
"GIT_COMMITTER_NAME": "Kayos",
|
||||
"GIT_COMMITTER_EMAIL": "kayos@sulkta.com",
|
||||
"GIT_AUTHOR_NAME": author_name,
|
||||
"GIT_AUTHOR_EMAIL": author_email,
|
||||
"GIT_COMMITTER_NAME": author_name,
|
||||
"GIT_COMMITTER_EMAIL": author_email,
|
||||
"PATH": "/usr/local/bin:/usr/bin:/bin",
|
||||
}
|
||||
msg = (
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ Authentication model:
|
|||
- Tokens are flagged is_admin=1 or 0. Admin can do everything.
|
||||
- Per-app tokens (is_admin=0) can register projects (becoming the owner)
|
||||
and only see/touch projects where owner_token matches their name.
|
||||
- Cross-token project access returns 404 (NOT 403) — same existence-leak
|
||||
guard clawdforge uses for sessions.
|
||||
- Cross-token project access returns 404 (NOT 403) — existence-leak guard.
|
||||
|
||||
Endpoints:
|
||||
- GET /healthz — public-ish (still needs LAN IP)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue