Skip to content

Release: org default remember expiry, Allow split button, template summaries, /health on DB - #848

Merged
angel-manuel merged 11 commits into
masterfrom
release/dev-to-master-2026-10-29
Oct 30, 2026
Merged

angel-manuel merged 11 commits into
masterfrom
release/dev-to-master-2026-10-29

Conversation

@angel-manuel

Copy link
Copy Markdown
Contributor

Release dev → master. It contains 10 commits since v0.25.0 (#839), two decisions (D141, D142) and migration 139. git cherry origin/dev origin/master is empty.

What's in it

⚠️ Notes

🤖 Generated with Claude Code

github-actions Bot and others added 11 commits October 27, 2026 18:24
…840)

The overspiral.com GCP org enforces domain-restricted sharing
(iam.allowedPolicyMemberDomains), which rejects new allUsers invoker
bindings. Disable the invoker IAM check on the api, overfwd and shortener
services instead, and forget the old bindings with `removed` blocks so
the apply never leaves a service IAM-gated mid-flight.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
OSV started flagging GHSA-qwgh-2vcv-g2f7 (block-buffer) and
GHSA-gcqx-w48m-w2h4 (deepmerge), turning the daily Dependency audit and
every PR's OSV scan red. block-buffer 0.12 moves to the fixed 0.12.1.
0.10.4 (pinned by digest 0.10) and deepmerge (dev-only) have no fixed
release; both are excepted for 90 days with the reasoning in
dependency-vulnerability-policy.md.

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
)

* feat(infra): remove default-SA Editor and set project org policies

Google's IAM Recommender flagged roles/editor on the default Compute
Engine SA (0 permissions used in 90 days) and on the cloudservices agent
(12 used, all the VPC connector's instance group). Both were project-
creation defaults that nothing in Terraform owned.

modules/project-guardrails removes both with google_project_iam_member_remove,
granting the agent roles/compute.editor first where the VPC connector
exists. It also sets project-level org policies now that both projects
sit in the overspiral.com org: the default-SA pair, the audit-exemption
ban, public access prevention, and the Cloud SQL public-IP pair (enforced
in prod, explicitly off on dev). An import block adopts dev's hand-set
key-creation opt-out.

Not applied: docs/runbooks/project-guardrails.md has the operator steps.
Dev's default-SA binding was already removed by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(infra): make the Cloud Run removed blocks' destroy = false explicit

A bare removed block already forgets the old allUsers invoker binding
without deleting it; OpenTofu warns that the intent is implicit. Same
behaviour, no warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(runbooks): ADC quota project for the org-policy apply

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* ci(infra): validate with OpenTofu 1.13 so removed blocks may carry lifecycle

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(infra): bill provider API quota to the managed project

Org Policy rejects user-ADC calls without a quota project, so
`make tofu-plan` failed reading project-guardrails policies. Set
user_project_override + billing_project on both providers and enable
Cloud Resource Manager in the API list, which the provider's own reads
now count against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(runbooks): quota project now comes from the provider config

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(casa): record the applied org-policy baseline and guardrails

Both projects are in the overspiral.com org, which enforces a baseline
at org level; project-guardrails is applied to dev and prod. Replace the
pending-apply notes with the measured effective policy per constraint,
note the removed allUsers invoker bindings, and narrow the open items to
run.allowedIngress and the Recommender capture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(casa): track run.allowedIngress as its own evidence row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(todo): split run.allowedIngress out of the org-policy baseline item

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…own, TCP probes (#843)

* feat(infra): prod uptime check + [P0] API Down, enable PromQL alert gates

Prod had no GCM uptime check and no API-down page: the monitoring module
gates both on api_domain, which main.tf fed from var.domain, and prod leaves
domain empty because the GCLB serves api_host_suffix. Fall back to
api_host_suffix when the LB is on.

The three PromQL gates (api_latency, oauth_refresh, upstream_error) are on in
both envs; their descriptors were measured present 2026-10-27. The OAuth,
upstream and webhook ratio queries clamped a per-second denominator to 1,
which at our volume made them unable to fire; they now use a 0.001 floor plus
a minimum-sample guard, as the latency alert already did. Same fix on the two
Actions & OAuth dashboard ratio charts.

Runbook: docs/runbooks/uptime-and-alerts.md. Not applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(api): /health 503s when Postgres is down; Cloud Run probes are TCP

The HTTP liveness probe on /health (1s default timeout) lost the race with
the 2s DB check once Cloud SQL went away, so dev's instance was shut down
~90s into every nightly stop and no replacement could boot: Cloud Run
answered 500 until morning. The always-200 /health existed only to protect
those probes, and it did not.

Probes now open a TCP socket on the container port (the listener binds only
after create_app has connected, migrated and preflighted, so startup loses
nothing). /health shares /ready's gate: 200 ok, or 503 degraded when the DB
probe fails, so [P0] API Down covers the database too. Dev's nightly API
Down is accepted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Allocated by .github/workflows/allocate-decision.yml. The authoring PR wrote D-NEXT; this commit is the mapping from D141 to the PR that decided it.
…oval detail (#844)

* feat(dashboard): single Allow split button with duration menu on approval detail

Folds "Allow once", "Allow & Remember" and the expiry clock into one primary
split button: the caret picks Once / remember For 1h…30d / Always, the main
half runs it. Once resolves `allow`; any other choice resolves
`allow_remember` at the "Remember as" scope with that TTL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(dashboard): screenshot-approvals waits for load, not networkidle

Authenticated pages hold an SSE stream open, so networkidle never fires and
goto times out — the same reason snap.mjs dropped it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…days) (#846)

* feat(approvals): org-configurable default Allow & Remember expiry (7 days)

Orgs get default_remember_ttl_secs (migration 139; NULL = forever,
60s..365d, default 7 days, backfilled to existing orgs), exposed on
/v1/orgs/{id}/execution-settings and as a select in Org Settings.

An allow_remember resolve with no ttl now takes the org default instead
of minting a permanent rule; "forever" is accepted explicitly. The
dashboard expiry picker and the MCP remember dialog preselect the org
default, and the dashboard, MCP and SDK card send "forever" explicitly.
One parser (parse_rule_ttl) now serves /resolve and permission edits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(dashboard): space before the Allow menu's "· default" tag

Svelte trimmed the leading space inside the tag span, so it read
"For 7 days· default". Screenshot script waits out the menu fade-in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Allocated by .github/workflows/allocate-decision.yml. The authoring PR wrote D-NEXT; this commit is the mapping from D142 to the PR that decided it.
…845)

* fix(slack): name channels in approval summaries, log resolver misses

A prod Slack approval read "to C0123…" though slack.yaml declares a
conversations.info resolver: the HTTP resolver drops every failure
silently, and Slack answers its own (missing_scope, channel_not_found)
in-band as 200 {"ok": false}, so there was nothing to diagnose from.

- HTTP display resolvers log transport errors, error statuses and empty
  projections, with the upstream's short `error` code; never the URL or
  the argument. Mirrors the MCP path, which already logged.
- slack.yaml: channels render as '#general'; get_thread_replies gains the
  channel resolver and get_user a users.info resolver.
- Tests: approval title names the channel, an unresolvable channel falls
  back to the raw id, read audit rows carry the resolved names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(resolver): strip the URL from a logged resolver transport error

reqwest's Display quotes the request URL, which carries the substituted
argument the log line was written to keep out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(templates): info.summary as a one-line catalog tagline

`info.description` is written for agents and runs to paragraphs, which
is too long for a catalog tile. Read the standard OpenAPI 3.1
`info.summary` as a short dashboard-facing tagline and expose it as an
optional `summary` on `/v1/templates` (list, search, detail, admin,
draft preview). It is omitted when unset, and agent-facing `/v1/search`
and MCP keep `description`.

- Compile warns (never refuses) on a multi-line value or one over 80
  chars. The same check covers a derived layer's new `delta.summary`
  relabel.
- Every shipped template, plus the synthetic `http` service, now has
  a summary. `every_shipped_template_has_a_short_summary` keeps them
  short.
- The dashboard Create Service cards show `summary ?? description`
  with the full description as a tooltip, and template search matches
  on summary too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(templates): a blank delta.summary inherits instead of blanking the base

Trim the relabel like info.summary, and treat whitespace-only as unset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Factory <factory@overslash.dev>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
overslash Ready Ready Preview Oct 29, 2026 1:58pm UTC

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

Code diff size

+847 / −120 across 43 files (net +727)

Area Files Added Removed Net
dashboard 10 +405 −37 +368
overslash-api 16 +252 −75 +177
overslash-core 13 +143 −3 +140
overslash-db 1 +34 −1 +33
sdk 3 +13 −4 +9

Source files under src/ only (.cjs, .go, .js, .jsx, .mjs, .py, .rs, .svelte, .ts, .tsx); test files and inline #[cfg(test)] modules excluded. 71 other changed files not counted.

@codecov

codecov Bot commented Oct 29, 2026

Copy link
Copy Markdown

@angel-manuel
angel-manuel merged commit f5b27a0 into master Oct 30, 2026
48 of 49 checks passed
@angel-manuel
angel-manuel deleted the release/dev-to-master-2026-10-29 branch October 30, 2026 11:01

This branch was successfully deployed

1 active deployment
Preview — 7b5b9ea7 Deployed Oct 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant