You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Minor Changes
f1d60da: Add a platform-admin surface for the chat analysis pipeline's per-organization settings. A new adminChatAnalysis management service (getSettings / upsertWorkUnitsSettings, session-only, gated on the platform-admin flag) reads and writes the organization's chat_analysis_settings row for the work-units judge, taking the same organization advisory lock the reservation transaction holds and recording before/after audit snapshots under the new chat_analysis_settings subject. The developer toolkit's Features tab gains a matching "Work Units Chat Analysis" section: an org-wide enable/disable control plus the daily evaluation cap, with a suggested cap prefilled when enabling an organization that never had one. A third method, triggerAnalysis, wakes the chat analysis coordinator of every project in the organization on demand — surfaced as a "Run now" button in the same section — so an admin can start a pass immediately instead of waiting for a chat write or the periodic sweep.
861e650: Add on-demand LLM session summaries (chat.summarize) and pin controls on Agent Sessions: persisted summaries in the session side panel, pin/unpin on list rows and the detail sheet, and a Pinned filter.
e1b188a: chat.load now accepts a producer-scoped API key (Gram-Key) in addition to a dashboard session and a chat-session token, so backend integrations can pull chat transcripts programmatically without a browser session. Only a direct producer API key is treated as a first-party project credential: like the dashboard session (and the way RBAC already exempts API keys via ShouldEnforce), it can load any chat in its project, including chats owned by an external user. External-user callers and chat-session tokens stay owner-matched even when the token carries the minting key's APIKeyID, and the project/org boundary still applies. The dashboard's producer key-scope description now notes it can export chat transcripts, and the endpoint is added to the public SDK/docs allowlist so its API-key auth is captured in the published API docs.
ffae6fa: Add daily custom-domain routing and TLS certificate health checks in an observation-only first release: checks log their findings, including the admin notifications a future release will send, without persisting health state or emailing anyone yet. The dashboard groundwork for health warnings and a manual recheck ships alongside but stays dormant until observation ends.
cb9189c: Add Claude Opus 5 (anthropic/claude-opus-5) to the supported model catalog and make it the default for in-app chat and newly created assistants. Specialized judge, embedding, and other purpose-specific model selections remain unchanged.
35fad1f: Add the schema foundation for device integrations — the framework that connects an organization to external device-management and compliance vendors. Three new tables: device_integration_configs (the audited, per-org, per-provider integration identity, with secret credentials as an encrypted write-only JSON blob and non-secret settings in readable jsonb), device_integration_syncs (scheduler state per config and schedule, modeled on ai_integration_syncs including the separate auto-paused vs user-disabled markers, plus a pushed-snapshot digest so evidence sinks can skip no-op pushes), and mdm_devices (the MDM-reported hardware inventory, keyed by config with both the raw MDM-reported user email and a resolved users.id, and a missing_since lifecycle instead of deletes). Also adds a case-insensitive (organization_id, LOWER(email)) index to device_agent_syncs, the agent-heartbeat side of the upcoming coverage join.
03b0c2e: Add platform-admin management of Gram's own platform-level external credentials (starting with the ambient GCP identity) via a new adminExternalCredentials API (create, read, update, delete) and an "External Services" section in the organization settings with a creation sheet and a per-credential detail page. Includes a live "who am I" Verify probe backed by a reusable gcpauth identity resolver.
084cc71: Add Budgets v1: org-scoped per-person budget rules with CEL actor targeting over directory-synced attributes. A periodic Temporal evaluator sums each matched actor's LLM spend from ClickHouse against the rule's per-person limit for UTC calendar windows, records warning/breach events, and publishes circuit state to Redis. Rules with action=block deny the blocked user's Claude Code traffic (UserPromptSubmit and PreToolUse, before risk-policy scans) until the window resets. Rules are append-only version snapshots: editing archives the current version row and creates a successor (version + 1), and rules are archived — never deleted — so historical events always resolve to the exact config that fired them. In the dashboard, Budgets renders as a tab on the Costs page wired to the new spendrules management API (rule create/edit/archive, live actor preview, overview cards, events tab); the tab only appears when the gram-budgets-page PostHog flag is enabled, so the surface can be released to select users.
Patch Changes
6801c36: Make Codex MCP tool calls joinable to their recorded provenance (DNO-604). Codex hook payloads carry no per-call tool-call id, so the recorded chat tool-call id (previously the tool name) and the telemetry trace id (previously derived from the session id) could never satisfy the shadow-MCP provenance join trace_id = sha256(tool_call_id)[:16] — every Codex MCP call fell back to x-gram-toolset-id signature validation. Both sides now derive from a shared sessionID + "|" + toolName key, which also moves Codex trace grouping from one-trace-per-session to one-trace-per-(session, tool): Tool Logs rows now carry the actual tool name instead of an arbitrary one per session. The canonical ingest path applies the same shared-key fallback for any sender that omits per-call tool ids.
995ac90: Enabling an MCP server no longer fails when the project's Default plugin already lists a server under the same display name. The Default-plugin attach now picks the first available display name — the requested one, then a backend-id-suffixed variant — instead of letting the (plugin_id, display_name) unique index abort the enclosing transaction, so a same-named toolset attachment or a stale row can't block enablement. Deleting an MCP server also detaches it from its plugins (recording a plugin:server_remove audit event per detachment), releasing the display name for a replacement server.
32df5c0: MCP servers backed by an external OAuth authorization server now serve RFC 8414 authorization-server metadata whose issuer matches the Gram resource URL, so spec-compliant OAuth clients no longer reject the document.
52cc585: Serve the hooks@0.3.4 binary to hook installations. Previously pinned releases stay available so installations that have not regenerated their bootstrap script can still install.
8fa329b: Serve the hooks@0.3.5 binary to hook installations. Previously pinned releases stay available so installations that have not regenerated their bootstrap script can still install.
e6d11cd: Remove the unused Kubernetes Gateway API custom-domain provisioner. No environment ever enabled it and no cluster has the Gateway API CRDs installed; custom domains are provisioned exclusively through Ingress. This also unblocks the custom-domain health sweep, which failed while trying to list HTTPRoutes on clusters without the Gateway API.
8bfe95d: Dashboard session tokens are now generated from 256 bits of crypto/rand entropy (base64url-encoded) instead of a v4 UUID. Session tokens are bearer credentials validated by a bare cache lookup, so they must be unguessable; a UUID carries only 122 bits of entropy in a recognizable, structured format and is not intended for use as a security token. Existing sessions remain valid, this only affects newly issued tokens.
3f3e59e: Keep published plugin server names in sync when their MCP server is renamed.
dd0089e: Remove the telemetry-logs-pubsub-shadow PostHog killswitch from the telemetry Pub/Sub shadow dual-write; rows written to telemetry_logs are now always mirrored to the gram-telemetry-v1-log-record topic. The flag was evaluated locally with a constant distinct ID and no groups, which cannot satisfy a group-targeted release condition — evaluation failed on every batch and the fail-closed gate meant nothing was ever published (while emitting a warn log per batch). The publish path is already best-effort and non-blocking, so the extra killswitch added more failure surface than safety.