Commit Graph
41 Commits
Author SHA1 Message Date
inference-bot f45ca199cf manifest: build on-server (drop the registry image pin)
The remote registry builder is currently unusable from this Cloudron host:
its in-build `docker login registry.inference.coop` resolves the registry to
127.0.0.1:443 and is refused, so no new image can be pushed to the registry
(the box's own docker CAN reach the registry — a pull of a missing tag returns
a clean 404 — so this is the builder's container network, not the registry).
The panel and dashboard are already unpinned and build on-server via
`cloudron update` from the repo dir; the portal joins them so its code can ship
the operator-spend breakout the dashboard reads. Restore the pin when the
builder is fixed.
2026-11-02 15:49:11 +00:00
inference-bot 8fc670b240 manifest: pin to 20261102-5f8bed3 2026-11-02 15:42:38 +00:00
InferenceBot ddeefdebe0 manifest: pin to 20261101-6a7eaf0 2026-11-01 18:00:30 +00:00
inference-bot b065b7301f manifest: correct the registry path in the pin
I had rewritten co-op/member-portal to code/member-portal while bumping the tag. The repository path in a live pin is the registry location the image is stored and fetched from; changing it points Cloudron at a repo that does not hold this app. Only the tag should move.
2026-11-01 17:17:13 +00:00
inference-bot abdc56e84c manifest: pin to 20261101-e1ec25f
Tag names the commit it was computed from, after committing the agent all-time-spend change.
2026-11-01 17:17:00 +00:00
inference-bot 5beffaf7d5 manifest: pin to 20261031-6f6957c 2026-10-31 16:58:03 +00:00
inference-bot d2b6f1551f manifest: pin to 20261031-b998d8d 2026-10-31 16:53:50 +00:00
inference-bot c21421a89b manifest: pin to 20261031-7d2507a 2026-10-31 16:50:01 +00:00
inference-bot 7d2507a927 portal: 90% threshold for budget notices; sweep 3x a day
Trigger becomes proportional (90% of the balance used) instead of a $2 floor, so a member on $15 and one on $35 are treated the same. The once-per-crossing latch keys on the same fraction. membership_sweep moves from '0 3 * * *' to '0 3,11,19 * * *' so the notice arrives within hours of crossing rather than up to a day later. BUDGET_NOTICES remains off.
2026-10-31 16:49:22 +00:00
inference-bot 26be6156ae manifest: pin to 20261031-d5fbb2e (previous commit dropped the date prefix and 404ed the pull) 2026-10-31 16:44:23 +00:00
inference-bot bb864055e6 manifest: pin to d5fbb2e (computed before the commit again — the code commit is 49e79aa) 2026-10-31 16:35:48 +00:00
inference-bot d5fbb2ed84 portal: budget notice -> generic low-balance wording, $2 floor, username, once per crossing
Wording no longer names an allowance or a credit pack: it says balance, so it is true whether the member is short on allowance, on purchased credit, or both. Trigger is an absolute $2 floor on remaining budget rather than a percentage, so it means the same at any budget size. Recipient greeting uses members.slug (the username) instead of the email local part, which produced 'Hi n,'. The once-only latch now clears when the balance rises back above the floor, so it fires once per crossing rather than once per budget cycle. BUDGET_NOTICES stays off.
2026-10-31 16:35:35 +00:00
inference-bot 49e79aadcc manifest: pin to 20261031-87e7c5b (the earlier pin named the pre-commit hash) 2026-10-31 16:25:51 +00:00
inference-bot 87e7c5b30e portal: budget notices by email, off by default
Warns a member at 80% of their monthly cap and again when it is exhausted, using the welcome email's template shell. Spend and budget come from LiteLLM's Postgres, the same source the dashboard shows. One notice per level per budget cycle. BUDGET_NOTICES=off|dryrun|on gates sending; POST /admin/budget-notices previews at any time and refuses to send unless the flag is on. Rides the existing sweep cron, wrapped so it cannot break reconciliation.
2026-10-31 16:25:36 +00:00
inference-bot 76d59b3fb6 manifest: pin dockerImage to 20261030-6475a51 2026-10-30 19:22:05 +00:00
inference-bot e5c6b6060e manifest: pin dockerImage to 20261029-9f198fc 2026-10-29 21:20:19 +00:00
inference-bot a0040f52e0 manifest: pin dockerImage to 20261029-592cf83 2026-10-29 20:57:38 +00:00
inference-bot 42cf43a125 manifest: pin dockerImage to 20261029-42bdfa2 2026-10-29 04:19:33 +00:00
inference-bot ceeaf277e2 manifest: pin dockerImage to 20261028-a5410ac (inlined key crypto) 2026-10-28 17:11:40 -06:00
inference-bot 4a48529cbb manifest: pin dockerImage to 20261028-3ee385d-nc (rebuilt no-cache, keycrypto present) 2026-10-28 17:01:36 -06:00
inference-bot 8ee1c8cea5 manifest: pin dockerImage to 20261028-3ee385d (key encryption at rest) 2026-10-28 16:50:20 -06:00
inference-bot ac3d79a1df manifest: pin dockerImage to 20261028-a0d15e3 (sweep legacy-token cleanup) 2026-10-28 13:54:04 +00:00
inference-bot e773c5097f manifest: pin dockerImage to 20261028-0ae1404 (carbon unit fix) 2026-10-28 04:35:05 +00:00
inference-bot 997d047323 manifest: pin dockerImage to 20261028-8e9906d (impact column fixes) 2026-10-28 04:34:06 +00:00
inference-bot 89593cfa74 manifest: pin dockerImage to 20261028-af610fe (energy and carbon metrics) 2026-10-28 04:32:20 +00:00
inference-bot 5a9b0d2b0d manifest: pin dockerImage to 20261028-27d30a1 (broker metrics route fix) 2026-10-28 04:17:18 +00:00
inference-bot acd01afc99 manifest: pin dockerImage to 20261028-4ffadd2 (broker metrics route) 2026-10-28 04:15:19 +00:00
inference-bot 6ab0554d00 manifest: pin dockerImage to 20261028-1cf78c4 (membership history fix) 2026-10-28 03:56:20 +00:00
inference-bot c5d5fa2fac manifest: pin dockerImage to 20261028-27c32fc (listmonk count fix) 2026-10-28 03:55:03 +00:00
inference-bot 80de75672c manifest: pin dockerImage to 20261028-70ae435 (daily metrics snapshot) 2026-10-28 03:53:39 +00:00
inference-bot 70ae435867 metrics: daily snapshot of members and usage, backfillable, plus a read route
The co-op had no longitudinal data: every number was an ad-hoc query, so
nothing compounded and no single source owned "how many members do we have,
and when did that change". That cost us a wrong figure in the newsletter ("six
new members" — actually 21; the six were forum joins).

New: metrics_snapshot.py writes one row per day into the portal's SQLite store
(the same members.db), and GET /admin/metrics/series returns them oldest-first
for the panel and dashboard to chart later.

  - Cumulative columns (members_active, members_total, members_new,
    newsletter_subs, matrix_space_members) are counts AS OF that day;
    spend_usd/requests are THAT day's traffic.
  - FAIL CLOSED PER METRIC: an unreadable source yields NULL, never a zero — a
    zero reads as "nobody" and would bake a lie into a chart. Failures print to
    stdout, and a scheduler task's stdout lands in the app log.
  - Listmonk's cached subscriber_count is NOT trusted (it reads 142 for a list
    holding 71): the count comes from paging the subscribers endpoint.
  - Member growth comes from welcome_sent_at, the provisioning timestamp —
    the closest thing the portal stores to a join date. Manual/founder members
    have no welcome email, so backfilled days are a documented LOWER BOUND;
    today's row carries the exact count.
  - Runs as an in-app scheduler task (addons.scheduler, 03:15 UTC) rather than
    an agent cron: member-facing plumbing should not depend on the agent VM.
  - Backfill is idempotent; member growth is reconstructible back to
    September and spend/requests back to the gateway's first request.

Charts land later, on the surfaces, once the shape of the series is reviewed.
2026-10-28 03:52:49 +00:00
inference-bot 403a773f53 manifest: pin dockerImage to 20261027-452a27a (member-set guard + access-log redaction) 2026-10-27 05:04:44 +00:00
inference-bot c2369034ee manifest: pin dockerImage to 20261027-5720a63 (security fixes: admin token split, credit-pack order verification, revoke on lapse) 2026-10-27 03:34:29 +00:00
inference-bot 5720a63958 security: separate admin token, verify credit-pack orders, revoke access on lapse
Member disclosure, three findings (fixes 1-3 of 5):

1. WEBHOOK_TOKEN was both the Open Collective webhook URL token and the
   X-Admin-Token for every /admin/* route, so anything that learned the webhook
   URL (OC admins, OC logs, this app's access logs) gained portal admin. The URL
   token is forced by OC's generic webhooks, which cannot set headers — the reuse
   is not. Introduce ADMIN_TOKEN, header-only. ADMIN_TOKEN_LEGACY=1 (default)
   still accepts WEBHOOK_TOKEN and logs a warning, so the admin panel and the
   scheduler keep working; set ADMIN_TOKEN everywhere, then flip it to 0 and
   rotate. sweep.sh and the digest script now send ADMIN_TOKEN.

2. The credit-pack path fell back to the webhook payload's own amount when OC
   could not resolve the order, so a forged POST naming its own totalAmount
   minted credits for any slug. The payload is now a hint only: an unresolvable
   order is refused, logged loudly, and emailed to the operator for manual
   reconciliation. Transient OC failures hold instead of granting blind.

3. Lapsing did not revoke access: both deactivation sites (lapse webhook, nightly
   sweep) discarded the key token deactivate_member() returns. Member keys carry
   no max_budget of their own, so they inherit the team's — zero the team budget
   on deactivation, which blocks every key under it. Key deletion is deliberately
   NOT used: provisioning reuses the stored sk- token on reactivation, and
   get_or_create_team does not update an existing team's budget, so the two
   renewal paths now re-sync the budget explicitly. Failures are loud (log +
   alert email); deactivation still completes.
2026-10-27 03:31:40 +00:00
Ubuntu 250ca6e8f0 manifest: pin dockerImage to 20261026-9495daa (the image now running) 2026-10-26 16:45:22 +00:00
Ubuntu ac0bdb6518 manifest: pin dockerImage to the deployed tag
The repo didn't record which image is live, so it couldn't answer "what is
deployed here?" — the tag lived only on the Cloudron app. Pin it to the image
deployed 2026-10-26 so the repo mirrors production, as our other repos do.

Consequence, same as librechat-custom: when the CLI runs from this directory this
manifest now wins over `cloudron update --image <tag>`, so a future release pins
the new tag here and commits it as part of the deploy.
2026-10-26 16:27:53 +00:00
Inferencebot bca11a1657 Move docs-RAG refresh into the portal container (Gitea raw API + scheduler addon, 3:30am daily) 2026-10-12 19:23:00 -06:00
Inferencebot cb04958460 scheduler addon belongs under addons (manifest schema), not top level 2026-10-12 18:23:50 -06:00
Inferencebot b58929076e Restore nightly membership sweep scheduler (3am daily) — was silently missing from manifest 2026-10-12 18:21:27 -06:00
inference-bot c1866df2a4 Add email notifications (sendmail) + membership sweep (scheduler): welcome email on webhook, reconcile endpoint, daily sweep 2026-09-11 13:45:18 -06:00
inference-bot 451fb561bc Scaffold member portal: OC webhook + Cloudron user mgmt + LiteLLM key injection 2026-09-04 17:06:27 -06:00