feat(skills): add compliance-portal-commitments skill
Adds a @probo/skills skill for creating and updating the public commitments (commitment groups and their commitments) shown on a Probo compliance portal. Commitments are grounded strictly in the organization's own published Probo policies and written in a factual, understated engineering voice, following the get context -> draft -> filter -> publish workflow via the Probo MCP. - skills/compliance-portal-commitments/SKILL.md - references/voice.md, references/portal-mechanics.md - CHANGELOG.md entry under Unreleased Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed by
Bryan Frimin
parent
0dc64e1944
commit
2adcc9ab5c
@@ -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
|
||||
|
||||
152
packages/skills/skills/compliance-portal-commitments/SKILL.md
Normal file
152
packages/skills/skills/compliance-portal-commitments/SKILL.md
Normal file
@@ -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 <company name>"** (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 <company name>", 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 <company name>" 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.
|
||||
@@ -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 <company name>".
|
||||
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 <company name>". 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 <company name>". 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.
|
||||
@@ -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 <company name>". 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.
|
||||
Reference in New Issue
Block a user