Skip to content

server@0.94.0

Choose a tag to compare

@gram-bot gram-bot released this 28 Jul 04:31
dd2fc0b

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.