diff --git a/packages/skills/CHANGELOG.md b/packages/skills/CHANGELOG.md index 663b2231c..4d0b15c32 100644 --- a/packages/skills/CHANGELOG.md +++ b/packages/skills/CHANGELOG.md @@ -5,6 +5,13 @@ this file. ## Unreleased +### Added + +- Skill: `compliance-portal-commitments` — create or update the public + commitments shown on a Probo compliance portal, grounded strictly in the + organization's own published Probo policies and written in a factual, + understated engineering voice (references: `voice.md`, `portal-mechanics.md`) + ## [0.1.0] - 2026-07-10 ### Added diff --git a/packages/skills/skills/compliance-portal-commitments/SKILL.md b/packages/skills/skills/compliance-portal-commitments/SKILL.md new file mode 100644 index 000000000..86774f92c --- /dev/null +++ b/packages/skills/skills/compliance-portal-commitments/SKILL.md @@ -0,0 +1,152 @@ +--- +name: compliance-portal-commitments +description: >- + Create or update the public commitments (commitment groups and their commitments) shown on a Probo + compliance portal, grounded strictly in the organization's own published Probo + policies and written in a factual, understated engineering voice. Use this skill whenever the user + wants to add, write, draft, edit, rewrite, curate, trim, or publish compliance portal commitments, + "security commitments", or a compliance portal security section for a company on Probo; asks what + commitments to show for a company doing SOC 2 or ISO 27001; gives an organization name or ID and asks + to build out its compliance portal commitments; or wants existing commitments reworded to sound less like + marketing. Always pull the real published policies first, surface only the specific and differentiating + controls a skeptical security reviewer would find useful, and create or update them through the Probo + MCP. Never invent controls that are not in the published policies. +--- + +# Probo compliance portal commitments + +A Probo compliance portal can display **commitments**: short, public statements about the security controls a +company actually operates. They live in **commitment groups**. Put all of a company's commitments under a +**single group titled "Security at "** (for example "Security at Captain") with a one-line +description; each commitment is one card in that group. Do not split commitments across multiple groups. + +Each commitment has four fields: + +- **icon** — one value from a fixed set (see `references/portal-mechanics.md`) +- **eyebrow** — a short category label above the title (e.g. "Encryption", "Authentication") +- **title** — a short heading, under six words +- **description** — one plain sentence (two only if the second adds a genuinely separate fact) describing + what is true of the system, in the company's own voice ("We encrypt your data..."). One idea per card. + Describe the security property, not the policy or the procedure behind it. Do not stack facts, and do not + reference documents ("a formal X Plan that defines...") or internal ceremony (approval chains, ticket + logging). + +The reader you are writing for is a **technical buyer skimming your public trust page**, not an auditor +cross-checking evidence. They are skeptical of marketing but they are reading fast. Every claim must still +be true and verifiable, but write it plainly and in the company's own voice, speaking to the reader: first +person for what the company does ("We enforce MFA"), second person for what the reader gets ("your data"). +Aim for the way the security pages at routine.co/security and supabase.com/security read: short cards, one +outcome each, no policy prose. That register drives the whole workflow below. + +Work in four stages: **get context → draft → filter → publish**. Do not skip straight to publishing. + +--- + +## 1. Get context (read the real policies first) + +Commitments must trace to controls the company genuinely has. The source of truth is the organization's +**published policies** in Probo, not general knowledge about SOC 2 or ISO 27001. + +1. **Find the Probo MCP and the organization.** This environment may expose more than one Probo MCP + server (for example a US and an EU instance). Call `listOrganizations` on each until you find the one + that returns the target company, and use that server for every later call. Match the organization the + user named and capture its `id`. +2. **List the published policies.** Call `listDocuments` with `document_types: ["POLICY"]`. Policies with + a `current_published_major` are published. +3. **Read the actual content.** `getDocument` returns metadata only. To get the text, call + `listDocumentVersions` for each policy with `filter: {statuses: ["PUBLISHED"]}`, + `order_by: {field: "CREATED_AT", direction: "DESC"}`, `size: 1`. The returned version includes the + `title` and the full `content`. Fetch the policies in parallel. + +Read the substance, not just the titles. The specific, quotable facts live inside the statements: exact +algorithms (AES-256), protocols (TLS, SSH, VPN), tools (SAST, secret scanning), cadences (quarterly +access reviews, annual penetration test, daily backups retained 30 days), and mechanisms (signed commits, +protected main branch, SSO, MFA). These specifics are what make a commitment credible. + +Do not pull details from the web and do not assume a control exists because the framework expects it. If a +policy says "TLS", write "TLS", not "TLS 1.3". If it says data is retained per contract, do not invent a +fixed retention window. + +--- + +## 2. Draft candidate commitments + +All commitments go under one group titled "Security at ", so there is no theming decision to +make. Draft a single ordered list of the strongest cards, and order them so related ones sit next to each +other (for example encryption and backups, then access, then development, then operations). Do not create +multiple groups. Give the group one light line of description, or leave it off; keep it in the same direct +voice, not a policy heading. + +For each candidate commitment, write down which policy statement backs it. If you cannot point to a +sentence in a published policy, drop the commitment. This is the grounding check and it is not optional. + +Then apply the voice in `references/voice.md`. The tone is calm, factual, and technical, the way internal +engineering documentation reads. Load that file before writing any titles or descriptions; the difference +between a good and a bad commitment here is almost entirely tone. + +--- + +## 3. Filter: what earns a place + +The instinct is to publish everything. Resist it. A compliance portal that lists ten generic commitments is +weaker than one that lists five specific ones, because the generic entries signal "marketing" and make the +reader trust the whole page less. + +**Aim for roughly 6 to 8 short cards. Hard cap: at most 10 commitments in the group.** The +reference pages run 7 to 9 flat cards; that is the target feel. These caps are ceilings, not targets, and +fewer is usually better. If you have more strong candidates than fit, prioritize by importance to a +technical buyer and drop or fold the rest, then tell the user what you left out and offer to swap. + +**Keep a commitment when it is:** + +- **Specific** — names a real technology, cadence, or mechanism (AES-256, quarterly reviews, signed commits). +- **Differentiating** — not every SaaS company does it, or does it this concretely. +- **Verifiable** — an auditor could confirm it from evidence. + +**Cut a commitment when it is:** + +- **Generic** — a sentence that could appear unchanged on a hundred SaaS security pages. +- **Table-stakes with nothing specific to add** — the fact is expected and you have no concrete detail + that makes it interesting. +- **Thin or off-audience** — internal-culture or legal items that a vendor-security reviewer would skip + (code of conduct, office badge procedures, cookie policy). +- **Already shown elsewhere on the portal** — the compliance portal separately displays certifications and + frameworks (SOC 2, ISO 27001) and published documents. Do not add a "Certifications" commitment or + otherwise restate a badge, framework, or document the page already surfaces; it is redundant. Spend the + card on a control the portal does not already show. + +There is no fixed list of "always cut" topics. The same topic can be worth keeping for one company and not +another. For example, disaster recovery is worth publishing if the company rehearses failovers and can +state a concrete objective; it is worth cutting if the entry would just say "we have a DR plan and test it +yearly", which every vendor claims. Judge each candidate against the three keep-criteria above. + +Before publishing, show the user the proposed commitments and say briefly what you cut and why. +Let them adjust. They know which controls they want to lead with. + +--- + +## 4. Create or update in the compliance portal + +Once the user has agreed on the set, write it through the Probo MCP. The exact tool sequence, the icon +enum, ordering/rank behavior, and the common pitfalls (read/write scope errors, reusing existing empty +groups instead of duplicating them, deleting a whole group vs individual commitments) are in +`references/portal-mechanics.md`. Read it before making any write calls. + +Key habits: + +- Publishing to a compliance portal is **public-facing**. Confirm the final copy with the user before writing, + and treat creates, updates, and deletes as changes that change what visitors see. +- Create the single "Security at " group first (or reuse it if it already exists), capture + its returned `id`, then attach every commitment to that id. +- Never create a second group. If the portal already has other groups from a previous run, fold their + commitments into the one group and remove the extras (confirm with the user before deleting). +- After writing, give the user a compact recap of the live state (groups and their commitments). + +--- + +## Reference files + +- `references/voice.md` — the tone-of-voice rules and before/after examples. Load this before writing any + commitment copy. +- `references/portal-mechanics.md` — the Probo MCP tool sequence, icon enum, and gotchas. Load this before + any create/update/delete call. diff --git a/packages/skills/skills/compliance-portal-commitments/references/portal-mechanics.md b/packages/skills/skills/compliance-portal-commitments/references/portal-mechanics.md new file mode 100644 index 000000000..a292fd893 --- /dev/null +++ b/packages/skills/skills/compliance-portal-commitments/references/portal-mechanics.md @@ -0,0 +1,78 @@ +# Portal mechanics: creating and updating commitments via the Probo MCP + +Read this before making any write call. All tool names below are Probo MCP tools; the server prefix +varies by environment (there may be more than one Probo server, e.g. US and EU). Use the server whose +`listOrganizations` returns the target organization. + +## Tool sequence + +1. **Resolve the organization** — `listOrganizations`, match by name, keep the `id`. +2. **Resolve the compliance portal** — `getCompliancePortal` with `organization_id`. Keep + `compliance_portal.id`; every group call still takes it as the `trust_center_id` argument (the resource + was renamed from "trust center" to "compliance portal" but the ID parameter kept its old name). +3. **Read what already exists** — `listCommitmentGroups` with the `trust_center_id`, and + `listCommitments` with a `group_id`. Do this so you reuse the existing group instead of duplicating it. + Order by `{field: "RANK", direction: "ASC"}`. +4. **Create the single group** — all commitments live under one group titled "Security at ". + If it does not exist yet, `addCommitmentGroup` with `trust_center_id`, `title`, `description`; if it (or + any other group) already exists, reuse it. Capture the returned `commitment_group.id`. You need it to + attach commitments. +5. **Add commitments** — `addCommitment` with `group_id`, `icon`, `eyebrow`, `title`, `description`. These + can be sent in parallel once you have the group id. + +## Updating and deleting + +- `updateCommitmentGroup` — takes `id`; any of `title`, `description`, `rank` are optional. Null/omitted + fields are left unchanged. +- `updateCommitment` — takes `id`; any of `icon`, `eyebrow`, `title`, `description`, `rank` are optional. +- `deleteCommitment` — takes the commitment `id`. +- `deleteCommitmentGroup` — takes the group `id`. Deleting a group removes the commitments inside it, so + to remove a whole theme (and its commitments) you can delete the group directly rather than each + commitment first. + +## Ordering + +Both groups and commitments have a `rank` (1-based) that sets display order. New items get the next rank +in creation order. To reorder, pass `rank` to the update call. + +## Icon enum + +`icon` must be exactly one of these values: + +``` +LOCK_KEY, EYE_SLASH, FINGERPRINT, SHIELD_WARNING, SHIELD_CHECK, SIREN, KEY, LOCK, +CLOUD, DATABASE, GLOBE, EYE, USERS, CERTIFICATE, GAVEL, HEARTBEAT, BELL, BUG, CODE, SERVER +``` + +Sensible mappings: + +- Encryption / data at rest: `LOCK` +- Data deletion / privacy: `EYE_SLASH` +- Data inventory / storage: `DATABASE` +- Authentication (SSO/MFA): `KEY` +- Identity / least privilege: `FINGERPRINT` +- Production / infrastructure access: `SERVER` +- Source control / code: `CODE` +- Vulnerability scanning / testing: `BUG` +- Monitoring / logging: `EYE` +- Alerting: `BELL` or `SIREN` +- Threat / risk: `SHIELD_WARNING` +- Controls in place / audited: `SHIELD_CHECK` or `CERTIFICATE` +- Governance / legal / compliance: `GAVEL` +- Vendors / people: `USERS` +- Availability / uptime: `HEARTBEAT` +- Cloud / hosting: `CLOUD` +- Networking / public surface: `GLOBE` + +## Gotchas seen in practice + +- **`insufficient scope`.** The connected MCP token may be read-only for the compliance portal, or may not yet + have commitment write scope at all. If creates fail with `insufficient scope`, nothing was written. + Tell the user to re-authorize / refresh the Probo MCP connection with compliance-portal write scope, then + retry the same batch. Do not keep retrying the identical call; the scope has to change first. +- **One group only.** All commitments belong under a single group titled "Security at ". If + the portal already has a group (whatever its title), reuse it rather than creating a second one; rename it + with `updateCommitmentGroup` if its title is not "Security at ". If earlier runs left several + groups, consolidate: move commitments into the one group and delete the extras (confirm before deleting). +- **Publishing is public.** Creates, updates, and deletes change what visitors to the compliance portal see. + Confirm the copy with the user before writing. diff --git a/packages/skills/skills/compliance-portal-commitments/references/voice.md b/packages/skills/skills/compliance-portal-commitments/references/voice.md new file mode 100644 index 000000000..29f3529ca --- /dev/null +++ b/packages/skills/skills/compliance-portal-commitments/references/voice.md @@ -0,0 +1,106 @@ +# Voice: how commitments should read + +Write copy that sounds like it was written by a senior infrastructure engineer, not a marketing team. +The page is a public trust page, read by a technical buyer skimming fast. They are skeptical of marketing, +but they are not an auditor reading your evidence line by line. Write short, plain cards that state one +security outcome each. For the target feel, read routine.co/security and supabase.com/security: a card is a +heading and a sentence, never a paragraph of policy. + +Write in the company's own voice, speaking to the reader. Use the first person ("we") for what the company +does and the second person ("your data", "your workloads") for what the reader gets. This is the single +biggest lever against generic copy: "We encrypt your data at rest with AES-256" reads direct and specific, +where "Data is encrypted at rest with AES-256" reads like a policy clause. Prefer the active, direct form. +It stays factual; it is not marketing. + +Two tests for every sentence: +- **If it could appear unchanged on a hundred SaaS security pages, rewrite it.** +- **If it describes a document or a procedure instead of what is true of the system, rewrite it.** + +## Principles + +- State facts, not aspirations. First person is for what is already true ("We enforce MFA"), never for + intentions ("We are committed to MFA", "We aim to..."). If it is not in place today, leave it off. +- Describe the security property, not the policy or the procedure. Say what is true of the system, not that + a document exists or what steps a process follows. Cut references to "a formal X Plan/Policy that + defines...", approval chains, and ticket logging. +- One idea per card. Do not stack two or three facts into one description; split them or drop the weaker one. +- Use specific technologies and practices where the policy supports them: TLS, AES-256, SAST, MFA, SSO, + signed commits, SSH, VPN, penetration testing. Naming the actual tool or provider (Snyk, the cloud + provider's SOC 2, Stripe for PCI) is concrete and reads well, when the policy supports it. +- Avoid adjectives unless they are measurable. "Encrypted with AES-256" is measurable; "industry-leading + encryption" is not. +- Body copy explains how something works, not why it is impressive. +- Calm and understated beats persuasive. Do not try to sound clever. +- Every claim must still be true and defensible, but write it for a reader skimming, not for an audit file. + +## Hard rules + +- No slogans, buzzwords, or inspirational language. +- No metaphors or analogies. ("No public door to production" is a metaphor; cut it.) +- No punchy two-sentence headlines. +- Headings under six words. +- Banned phrases and their kin: "built in, not bolted on", "best-in-class", "enterprise-grade", "we hunt + for threats", "around the clock", "bank-grade", "military-grade", "peace of mind", "always". +- Do not overclaim with absolutes. Prefer a plain statement of the control over "there is no way for X". + +## Titles + +Titles are short, up to six words. A plain noun label ("Least privilege by default") or a short active +statement ("MFA is enforced", "Every change is reviewed") both work. Not punchy marketing headlines, not +two-sentence slogans. The description carries the detail. + +- Prefer "MFA is enforced" over "SSO first. MFA always." +- Prefer "Data encrypted in transit and at rest" over "Encrypted at rest. Encrypted in transit. Always." +- Prefer "Every change is reviewed" over "Every commit signed. Every change reviewed." +- Prefer "Production access" over "No public door to production." + +## Descriptions + +One sentence is the default. A second only if it carries a genuinely separate fact. State the outcome and, +where the policy gives one, a specific mechanism or cadence, then stop. Keep a card to roughly 25 words. +One idea per card: if you are writing "X. Y. Z." with three separate controls, split them into separate +cards or drop the weakest. Read like a single line on a trust page a customer skims, not like a paragraph +lifted from the policy. + +## Before / after + +Three ways a card goes wrong: it reads like marketing, it reads like the policy it came from, or it is +written impersonally in the third person. The "Ship" line is short, direct, and in the company's own voice +(we/your). + +**Encryption** (marketing) +- Before: "Customer data is protected with industry-leading encryption from storage to transit." +- Ship: "Data encrypted in transit and at rest" / "Your data is encrypted in transit with TLS and at rest with AES-256." + +**Authentication** (impersonal) +- Before: "MFA is required for privileged accounts and critical systems." +- Ship: "MFA is enforced" / "We enforce MFA for privileged accounts and critical systems." + +**Least privilege** (policy prose) +- Before: "Access is granted on a least-privilege basis. Requests are approved by the system owner and logged. Access rights are reviewed quarterly." +- Ship: "Least privilege by default" / "We grant the minimum access needed and review it quarterly." + +**Secure development** (three facts in one card, so split it) +- Before: "Code is scanned with SAST and secret scanning. Container images are scanned before deployment. The production environment is penetration tested once a year." +- Ship, card 1: "We scan code and images" / "We scan code and container images before every deploy." +- Ship, card 2: "Pen-tested every year" / "We run an external penetration test once a year." + +**Incident response** (describes a document, not the system) +- Before: "Critical and security-related issues are handled through a formal Incident Response Plan that defines roles, procedures, and escalation." +- Ship: "Incident response" / "We investigate security incidents on a defined escalation path." + +**Monitoring** (policy prose) +- Before: "Application logs are retained for at least 30 days and aggregated to a central platform. Production outages trigger alerts to on-call engineers." +- Ship: "We monitor production" / "We centralize our logs and keep them 30 days. Outages page our on-call engineers." + +## Group description + +There is one group, titled "Security at ". Keep its description to one short line in the same +direct voice, or leave it off. "How we protect your data and our platform" is fine; a line like "How access +to systems and production is granted and reviewed" reads like a policy table of contents, which is the tone +to avoid. + +## A note on em dashes + +Do not use em dashes (—) in the copy. Use periods, commas, colons, or parentheses instead. This is a +standing preference of the person this skill was built for.