12 Commits

Author SHA1 Message Date
vikingowl 5d7ff6f061 docs: phase 2 design — usage prediction
Forward-looking signal: extrapolate the weekly buckets' burn rate from a
rolling history and alert when the projection lands before the natural
reset. Captures the design decisions made today (weekly buckets only,
linear regression over 6h, schema v2 with backward-compatible read,
configurable via env). Not yet implemented.
2026-05-18 18:14:47 +02:00
vikingowl c0bca5c12d feat(deploy): add scripts/build-push.sh for the Zot registry
registry.itsh.dev runs Zot, which only accepts OCI image indexes with SLSA
provenance attestations. A plain 'docker build && docker push' produces a
bare manifest and is rejected with 'manifest invalid' — the same gotcha
documented in self-hosted/ente.

The script mirrors that working pattern: buildx with --provenance mode=max,
--platform linux/amd64, integrated --push. Auto-detects the default tag
from cronjob.yaml so build-push and the manifest can't drift; override with
TAG= when releasing a new version.
2026-05-18 18:07:35 +02:00
vikingowl 6767b49649 fix(deploy): add itsh-registry imagePullSecret to CronJob
Same pattern as infinity-tales and marktvogt.de: the tenant-2 namespace
holds a pre-provisioned dockerconfigjson secret named itsh-registry that
authenticates pulls from registry.itsh.dev. Reference it from the pod
spec so the kubelet can fetch the image.
2026-05-18 17:53:57 +02:00
vikingowl d8e17ee22e fix(deploy): use tenant SA instead of custom RBAC
ITSH Cloud's multi-tenant model forbids tenants from creating Roles or
RoleBindings, so the custom least-privilege Role we shipped can't be
applied. The pre-provisioned 'tenant-2' ServiceAccount in the tenant
namespace already carries the necessary secret-patch permission, so we
just point the CronJob at it.

Also fixes the kustomize commonLabels -> labels deprecation.
2026-05-18 17:51:20 +02:00
vikingowl 3b3f1a9afa fix(deploy): point image at registry.itsh.dev with pinned 0.1.0 tag
Match the registry pattern used by infinity-tales and marktvogt.de.
Pinning to 0.1.0 instead of latest so deploys are deterministic; bump
the tag here when you push a new image.
2026-05-18 17:33:36 +02:00
vikingowl 49612841cd docs: add README with feature, deploy, and dev guides
Covers the reset-watcher feature design, K8s deployment flow with the
dedicated-bot-account rationale, the local docker test path via the
bootstrap script, the pytest -m live smoke test, and trust caveats
around the undocumented Anthropic endpoint and TOFU device handling.
2026-05-18 17:23:35 +02:00
vikingowl 107f9e1f14 feat(deploy): add Dockerfile, K8s manifests, and bootstrap script
Multi-stage Alpine build pinned to python:3.14-alpine, with libolm pulled
in only for the runtime layer. K8s manifests cover ServiceAccount, Role
(scoped to a single named Secret), RoleBinding, ConfigMap, RWO PVC, and
the CronJob itself (concurrencyPolicy=Forbid, runAsNonRoot, dropped caps,
readOnlyRootFilesystem). Kustomize overlay targets the tenant-2 namespace.
bootstrap-local.sh prepares ./local/ from a Claude install (honors
CLAUDE_CONFIG_DIR for work/priv splits) and prompts for the Matrix bot
credentials.
2026-05-18 17:23:24 +02:00
vikingowl 73ce3ad0df feat(reset-watcher): add config and CronJob entrypoint
Env-driven Config fails fast on missing required values; LOCAL_MODE relaxes
the K8s-specific knobs so the bot can run from a plain docker container
against a bind-mounted oauth-tokens dir. Entrypoint wires together token
refresh, usage poll, alert computation, optional armed cold-start message,
E2EE Matrix send, and atomic state persistence. Adds a pytest -m live
smoke test that hits the real /api/oauth/usage endpoint, skipped by
default so CI stays offline.
2026-05-18 17:23:12 +02:00
vikingowl 8ca1c7949e feat(matrix): add E2EE Matrix sender via matrix-nio
Async sender restoring login from a pre-obtained access_token + device_id
pair, with the nio sqlite key store persisted alongside watcher state.
Uses ignore_unverified_devices=True (practical TOFU) so headless sends
succeed against an encrypted room without manual cross-signing setup.
2026-05-18 17:23:01 +02:00
vikingowl b8af1e3bbc feat(clients): add Anthropic OAuth client and K8s Secret patcher
Targets the undocumented /api/oauth/usage endpoint that Claude Code uses
internally for /status. Token refresh uses /v1/oauth/token with the public
Claude Code client_id. On refresh, new tokens are persisted back via either
in-cluster K8s Secret PATCH (production) or atomic per-file write to the
mounted dir (local mode). utilization is converted from API's 0-100 percent
to internal 0.0-1.0 fractional at the boundary.
2026-05-18 17:22:49 +02:00
vikingowl 65c54416f3 feat(reset-watcher): add diff, state, and format logic
Pure functions for the watcher's core: compute_alerts decides what to emit
given prior state vs. fresh usage, with configurable threshold list and a
reset-shift tolerance to filter minute-boundary jitter. State is atomically
persisted as JSON. Alerts render to (plain, html) tuples for Matrix, with
severity-colored percentages, blockquote framing, and a Unicode progress
bar for the cold-start armed message.
2026-05-18 17:22:31 +02:00
vikingowl 4ff0c86bc5 chore: scaffold project structure and dependencies
Python 3.14 package layout for claude-matrix-bot, with reset_watcher as its
first feature. requirements pin matrix-nio[e2e] for E2EE and requests for
sync HTTP.
2026-05-18 17:22:21 +02:00