{"id":"platform-capabilities","type":"module","title":"Platform Capabilities (Connectors, Integrations, Branding, RBAC, Developer)","status":"ga","audience":["org-admin","developer","consultant"],"scope":"both","tier_min":"free","aliases":["15","control-plane","settings"],"summary":"The control plane that wires Klarum into an org's existing systems, governs who can do what, and exposes a developer surface. Supporting capability, not a headline tool.","keywords":["connectors","integrations","oauth","branding","rbac","roles","webhooks","scheduler","presets"],"body":{"what_it_is":"The control plane that connects Klarum to a firm's existing systems and the\nwider tender universe, governs who can do what, and exposes a\ndeveloper/automation surface. Supporting capability, not a headline tool.\n","what_it_helps_users_do":"Reach portals Klarum cannot read anonymously; bring documents in from where\nthey already live and send outreach from the org's own mailbox; put the org's\nidentity on every generated document; decide who may reach which part of the\nproduct; subscribe an external system to what happens inside Klarum; and keep\na personal working set of filters and alerts.\n"},"engines":[],"integrations":[{"id":"connector-ecepp","type":"integration","title":"ECEPP (EBRD)","summary":"The one live authenticated procurement-portal connector, via session login.","category":"procurement-portal"},{"id":"storage-google-drive","type":"integration","title":"Google Drive","summary":"OAuth storage connector feeding documents into the RAG and embedding knowledge base.","category":"storage"},{"id":"storage-sharepoint","type":"integration","title":"SharePoint","summary":"OAuth storage connector with two-way sync.","category":"storage"},{"id":"editor-microsoft-365","type":"integration","title":"Word and Microsoft 365","summary":"Editor integration behind a post-OAuth provisioning gate that refuses to record a connection for an unlicensed M365 service.","category":"editor"},{"id":"comms-outlook","type":"integration","title":"Outlook","summary":"Email connector that can be flagged primary outreach and performs a true send.","category":"comms"},{"id":"comms-gmail","type":"integration","title":"Gmail","summary":"Email connector that creates a draft rather than sending.","category":"comms"},{"id":"comms-teams","type":"integration","title":"Teams","summary":"Comms integration in the provider catalogue.","category":"comms"},{"id":"comms-slack","type":"integration","title":"Slack","summary":"Comms integration in the provider catalogue.","category":"comms"},{"id":"pm-linear","type":"integration","title":"Linear","summary":"Project-management integration in the provider catalogue.","category":"project-management"},{"id":"crm-hubspot","type":"integration","title":"HubSpot","summary":"CRM integration in the provider catalogue.","category":"crm"},{"id":"crm-salesforce","type":"integration","title":"Salesforce","summary":"CRM integration in the provider catalogue.","category":"crm"},{"id":"signing-docusign","type":"integration","title":"DocuSign","summary":"Signing integration in the provider catalogue.","category":"signing"},{"id":"automation-zapier","type":"integration","title":"Zapier and webhooks","summary":"Outbound automation via the webhook subscription surface.","category":"automation"}],"capabilities":[{"id":"firm-connectors","type":"capability","title":"Connectors","summary":"Authenticated pipes into procurement portals Klarum cannot read anonymously, with per-connector credentials encrypted at rest and a probe endpoint that validates them.","status":"ga","scope":null,"keywords":["ecepp","ebrd","credentials","encrypted","probe"],"body":{"what_it_is":"Authenticated pipes into procurement portals Klarum can't read\nanonymously. Today: **ECEPP (EBRD)** via session login. Roadmap (named in\nthe UI): **TED, AfDB, IADB**. Admin stores per-connector credentials\n(encrypted at rest); a probe endpoint validates; the ingestion pipeline\nharvests notices into staging.\n","what_it_helps_users_do":null}},{"id":"integrations-catalogue","type":"capability","title":"Integrations","summary":"A server-side provider catalogue spanning storage, editor, comms, project management, CRM, signing and automation, with OAuth callbacks and a post-OAuth provisioning gate.","status":"ga","scope":null,"keywords":["oauth","catalogue","provisioning-gate","primary-outreach"],"body":{"what_it_is":"A provider catalogue (server registry, all GA): Storage (Google Drive,\nSharePoint - OAuth, SharePoint two-way sync), Editor (Word/M365), Comms\n(Outlook, Gmail, Teams, Slack), Project mgmt (Linear), CRM (HubSpot,\nSalesforce), Signing (DocuSign), Automation (Zapier/webhooks). OAuth\nproviders redirect to the gateway callback; a post-OAuth \"provisioning\ngate\" prevents recording a connection for an unlicensed M365 service. One\nemail connector can be flagged **primary outreach**.\n","what_it_helps_users_do":null}},{"id":"ai-behavior-preferences","type":"capability","title":"AI behaviour preferences","summary":"Org-level generation preferences (tone, default output language, preferred and avoided terminology) that steer LLM drafting without touching matching scoring. Admin-only.","status":"ga","scope":null,"keywords":["tone","language","terminology","steering"],"body":{"what_it_is":"Firm-level generation preferences - tone\n(formal/persuasive/technical/concise), default output language\n(en/fr/es/ru), preferred/avoided terminology lists. Stored in\n`organizations.meta.ai_preferences` (admin-only).\n","what_it_helps_users_do":null}},{"id":"branding-assets","type":"capability","title":"Branding and portal","summary":"Per-org document branding assets - header logo (required for EOI generation), footer logo falling back to the header, and a cover hero image.","status":"ga","scope":null,"keywords":["logo","cover","eoi-gate"],"body":{"what_it_is":"Per-firm document branding assets: header logo (required for EOI\ngeneration), footer logo (falls back to header), cover hero image.\nGenerated EOI/bid documents carry the firm's identity automatically; the\nheader logo gates EOI generation.\n","what_it_helps_users_do":null}},{"id":"org-roles-rbac","type":"capability","title":"Organization and roles (RBAC)","summary":"Three built-in role tiers plus tokenised invite-by-email restricted to the org's admin domains, with an active-org header so a user can belong to several orgs.","status":"ga","scope":null,"keywords":["admin","signatory","standard","invitations","domains","seats"],"body":{"what_it_is":"Firm membership and role management (admin-gated). Three role tiers:\n**Admin** (full access), **Signatory** (can sign and submit EOIs/bid\ndocuments), **Standard** (view tenders, comment, collaborate).\n(`consultant_admin` is a higher platform/account role, not one of these\nthree firm tiers.) Invite-by-email with tokenised invites (7-day TTL,\nresend/revoke). **Domain discipline:** invitees must be at one of the\nfirm's admin (non-public) domains. Backed by\n`organization_members` / `organization_invitations` +\n`organization_membership_service.py`; org context honoured via an\nactive-org header so a user can belong to several firms. **Seat billing**\n(Business tier, per-seat metered): a seat is billed only when an invite is\n*accepted*; removing a member credits the unused remainder; Stripe is\nauthoritative.\n","what_it_helps_users_do":null}},{"id":"custom-roles-section-scoping","type":"capability","title":"Custom roles and section scoping","summary":"Business-tier admins define named roles and check which dashboard sections each may reach, derived from the org's plan so a role can never be granted an area the plan excludes.","status":"ga","scope":null,"keywords":["custom-roles","sections","plan-derived","presets"],"body":{"what_it_is":"Custom roles and section scoping are Business tier, admin-only. Beyond\nthe three built-in tiers an admin defines named roles at\n**Settings > Organization > Roles and access** and checks which dashboard\n**sections** each role may reach. The checklist is derived from the org's\nplan, so a role can never be granted an area the plan does not include.\nBacked by `org_roles.allowed_sections` and an admin-only roles API\n(Business gated), with a self-scope read returning a member's own scope;\n`organization_members.role` holds the role NAME, and a rename re-points\nassigned members in the same statement. Built-in presets can be renamed\nand re-scoped but not deleted, because every pre-existing role was\nbackfilled as a preset holding every section for an admin to narrow.\nAdmins are always unrestricted.\n","what_it_helps_users_do":null}},{"id":"developer-webhooks-capability","type":"capability","title":"Webhooks","summary":"Subscribe an external URL to org activity events. Delivery runs on the durable outbox with HMAC-signed attempts, exponential backoff and at-least-once semantics keyed on a stable delivery header.","status":"ga","scope":null,"keywords":["outbox","hmac","retries","at-least-once","dedupe"],"body":{"what_it_is":"Subscribe an external URL to firm activity events (pipeline/workspace\ntransitions, milestones, comments, tags, plus a modern\nworkspace/item/proposal lifecycle set). Delivery is fully implemented\nbackend-side and runs on the **durable outbox** (ADR-006 step 3b): firing\nan event writes a `webhook_deliveries` row plus one queue row, and a\nsupervised relay does the sending - so a delivery now survives a gateway\nrestart, at the cost of not being instantaneous (the first attempt lands\non the next relay tick, 5s by default). Each attempt POSTs with\n**HMAC-SHA256** signature headers (`X-Kl-Signature: t=...,v1=...`) and a\n10s timeout; failures retry with exponential backoff (5s/10s/20s) up to 3\nattempts, then the delivery is closed and the webhook's health pill\ncarries the reason (a blocked target, a subscriber that no longer exists,\nunreadable credentials, an unresolvable host, or the last HTTP status).\nDelivery is **at-least-once**: subscribers that must not process an event\ntwice should deduplicate on the `X-Kl-Delivery` header, which is stable\nacross retries of one delivery.\n","what_it_helps_users_do":null}},{"id":"developer-scheduler-capability","type":"capability","title":"Scheduler","summary":"Read-only admin observability over Klarum's cron jobs: last run plus full invocation history with status, latency, payload and replica id. Jobs run with cluster-singleton leader election.","status":"ga","scope":null,"keywords":["cron","apscheduler","leader-election","observability"],"body":{"what_it_is":"Read-only, admin-only observability over Klarum's cron jobs (last run +\nfull invocation history with status/latency/payload/replica id). Known\njobs: `daily_featured_refresh`, `daily_featured_email`,\n`daily_deadline_reminders`, `pipeline_ingest`. Jobs run on APScheduler\nwith **cluster-singleton leader election**, misfire grace, and coalesce.\n","what_it_helps_users_do":null}},{"id":"filter-presets","type":"capability","title":"Filter presets","summary":"Personal colour-coded bundles of feed filters. \"Standard\" is the org-profile baseline; each named preset overrides it per key, and the default one's score threshold drives the daily digest.","status":"ga","scope":null,"keywords":["presets","geography","cpv","threshold","digest"],"body":{"what_it_is":"Named, colour-coded bundles of outbound/featured feed filters\n(hierarchical geography + CPV pickers, include/exclude\nsource/method/category/notice-type). \"Standard\" is the firm-profile\nbaseline; each named preset overrides it per-key; one can be flagged\n**default**, and its **notification score threshold (0-10)** drives the\ndaily digest.\n","what_it_helps_users_do":null}},{"id":"product-catalogue","type":"capability","title":"Product catalogue","summary":"Klarum's own answer to \"what does this product ship\", published anonymously and in-app from one validated artifact, with the wiring graph behind the auth gate.","status":"ga","scope":null,"keywords":["catalogue","modules","graph","provenance"],"body":{"what_it_is":"A typed graph of every module, capability, surface, engine and\nintegration, authored in `docs/catalog/**.yaml` and validated against\nlive code before it can be published: dashboard sections against the\naccess-control keys, routes against the frontend route manifest, agent\ntools against the tool manifest, flags against the settings model, and\nevery relation the prose names against the expected database schema.\n","what_it_helps_users_do":"Read what the product ships without asking anyone, and tell what is\navailable today from what is on the roadmap, because every entry carries\nits plan tier and its shipping state.\n"}},{"id":"saved-searches","type":"capability","title":"Saved searches","summary":"Named outbound filter sets, saved per member and reusable across the opportunity feeds.","status":"beta","scope":null,"keywords":["alerts","cadence","sor","dedup"],"body":{"what_it_is":"Saved outbound filter sets with a notification cadence\n(real-time/hourly/daily/weekly/never) + in-app/email toggles.\n","what_it_helps_users_do":null}}]}