Getting Started with AuditBadger

3 articles M By Maciej Litwiniuk

Scaleway Setup Guide

How to connect a Scaleway project to AuditBadger with a dedicated read-only IAM application API key. Takes about 10 minutes. 1. Create the IAM application 1. In the Scaleway console, open IAM → Applications. 2. Create an application named auditbadger-compliance-reader. Do not use a personal (user-owned) API key — application keys are not tied to a human account and survive offboarding. 2. Create the read-only policy Open IAM → Policies, create a policy named auditbadger-compliance-read-only attached to the application, with two rule groups: - Organization scope: - OrganizationReadOnly - ProjectReadOnly - IAMReadOnly (lets AuditBadger verify the key stays read-only) - AuditTrailReadOnly (optional — only if you want Audit Trail evidence) - Project scope, limited to the project(s) you want monitored: - InstancesReadOnly - BlockStorageReadOnly - ObjectStorageBucketsRead - RelationalDatabasesReadOnly - SecretManagerReadOnly - Project scope, optional — grant only the products you actually use: - KubernetesReadOnly (cluster posture; AuditBadger never downloads kubeconfig files) - LoadBalancersReadOnly (TLS and certificate posture) - ContainerRegistryReadOnly (namespace visibility; images are never pulled) - VPCReadOnly and PrivateNetworksReadOnly (network segmentation inventory) Never grant FullAccess, Manager, Write, or Delete permission sets — AuditBadger detects them and blocks automated collection until they are removed. AllProductsReadOnly works but grants more read access than needed; AuditBadger will show a warning. 3. Generate the API key 1. Open IAM → API keys → Generate API key. 2. Select the auditbadger-compliance-reader application as the bearer. 3. Prefer no expiration so evidence collection is not interrupted; rotate the key manually instead. If you do set an expiration, AuditBadger shows the date and warns before the key expires. 4. Copy the access key and the secret key — Scaleway shows the secret key only once. 4. Connect in AuditBadger 1. Go to Account Settings → Integrations → Scaleway. 2. Fill in: label (e.g. "production"), organization ID, project ID, access key, secret key, and default region. 3. Save. AuditBadger validates the connection in the background, checks each product API, and verifies the read-only permission posture. 4. Once healthy, install evidence sources on your compliance controls (individually from a control, or in bulk via "Install evidence sources"). Key rotation 1. Generate a new API key for the same IAM application in Scaleway. 2. On the integration page, open Configuration, paste the new access key and secret key, and save. Evidence sources and collected evidence are kept. 3. After AuditBadger re-validates, delete the old API key in Scaleway. Troubleshooting - "Write-capable permissions detected" - the key's policy grants a write/full-access permission set. Replace the policy with the read-only sets above; collection stays blocked until fixed. - "Unrecognized permission set" - Scaleway added a permission set AuditBadger doesn't know yet. Collection is blocked as a precaution; contact support. - "Permission verification incomplete" - the key lacks IAMReadOnly, so AuditBadger cannot verify the policy. Collection still works, but the read-only posture is unverified. - A product shows "Permission denied" - the project-scope rule is missing that product's read-only permission set, or the policy is scoped to a different project. - Audit Trail source shows "setup required" - enable "Collect Audit Trail evidence" in the integration settings and grant AuditTrailReadOnly.

How Compliance Progress Is Calculated

Overview Every compliance project shows a single overall progress percentage, backed by eight section scores. The overall number is a weighted average — each section is scored from 0 to 100 on its own, then contributes a fixed share of the total. Progress measures how much of the work is recorded in the platform, not whether an auditor will accept it. A project at 100% is one where every document, control, and piece of evidence has reached its final state in AuditBadger. The Eight Sections And Their Weights - Documents — 20% - Controls — 20% - Evidence — 10% - Risks — 10% - Business Continuity — 10% - Vendors — 10% - Assets — 10% - Assessments — 10% Each section is the plain average of the items inside it. Ten controls scoring 100, 50, and 0 average out the same way you would expect — no item is weighted more heavily than another within its section. How Each Section Is Scored Documents (20%) Each policy document in the project scores: - 10% — someone has edited it at least once - 30% — published, when acknowledgements are required - 90% — acknowledgement assignments have been sent - 100% — published with no acknowledgement required, or every assigned person has responded A document reaches 100% as soon as everyone assigned has either accepted or rejected the acknowledgement. Rejections still count as a response — the score reflects that the acknowledgement round is finished, not that everyone agreed. Controls (20%) Each control in scope scores: - 10% — it has a description - 50% — a policy document or a piece of evidence is linked to it - 90% — implementation notes have been filled in - 100% — marked as implemented, not applicable, or accepted as an exception A control you deliberately rule out counts as complete. Marking something not applicable is a valid answer, and the score treats it that way. Evidence (10%) Each measured control scores by the furthest state any of its evidence has reached: - 0% — no evidence attached - 25% — evidence attached, still a draft - 50% — evidence submitted for review - 100% — evidence verified, or an automated check is passing Automated checks that pass with exceptions count as fully covered, the same as a clean pass. See "Which Controls Are Measured For Evidence" below — this is the section people most often expect to be higher than it is. Risks (10%) Each risk in your account scores 100% once it has been assessed, and keeps that score through treatment planning, treatment, acceptance, and closure. Risks still in draft or merely identified score 0%. In other words: identifying a risk does not move the number. Assessing it does. Business Continuity (10%) Each active business continuity process scores: - 0% — no exercises have been created for its plans - 50% — an exercise exists but has not been completed - 100% — at least one exercise has been completed Archived processes are ignored entirely. Vendors (10%) Each vendor scores by its review posture: - 100% — assessed, assurance reviewed, or recorded as an assurance exception - 50% — an assessment is in progress, or known-vendor data is available but not yet reviewed - 0% — never reviewed, review due, or action required Assets (10%) This section is all-or-nothing: 100% if your account has at least one infrastructure asset recorded, 0% if the inventory is empty. Assessments (10%) Each assessment attached to the project scores 50% while it is open and 100% once completed. Three Rules That Surprise People Empty sections count as zero, not "not applicable" A section with nothing in it scores 0% and still carries its full weight. An account with no risks recorded loses the entire 10% risk weighting — the section is not skipped and the remaining weights are not redistributed. This is the most common reason a project that "feels done" sits in the seventies. Before chasing individual items, check whether an entire section is empty. Four sections are account-wide, not project-specific Risks, Business Continuity, Vendors, and Assets are scored across your whole account, not per project. If you run a SOC 2 project and an ISO 27001 project side by side, both show the same score for those four sections, and work recorded in one immediately moves the number in the other. Documents, Controls, Evidence, and Assessments are specific to the project. Out-of-scope sections are excluded Controls belonging to a framework section you have marked as skipped are left out of both the Controls and Evidence sections — they are not counted as incomplete. Narrowing scope raises your percentage legitimately. Which Controls Are Measured For Evidence The Evidence section does not measure every control. A control is included when it is applicable and not a linked copy of another control, and then when either of the following is true: - it is expected to hold evidence directly — it has no structural sub-controls beneath it, and it is not a criteria-level heading such as a SOC 2 Trust Services Criterion - it actually has evidence attached, whatever its position in the hierarchy Two consequences are worth understanding: Parent controls with structural sub-controls are not measured directly. Their sub-controls are measured instead. Attaching evidence to the parent of a broken-down control does not raise the score — attach it to the sub-controls that need it. In ISO 27001, a control with attached supporting sub-controls can still hold its own evidence, and that evidence is counted. Attaching a shared sub-control to a control does not stop the control itself from carrying evidence. If it has its own evidence, it is scored on its own; if it has none, it stays out of the calculation and its sub-controls carry the coverage. Controls marked not applicable or accepted as an exception are excluded from the Evidence section entirely. They do not need evidence, so counting them as uncovered would understate your position. When The Number Updates Progress is recalculated in the background whenever meaningful work is recorded, including: - editing, publishing, or assigning a policy document, and completing an acknowledgement round - generating a control description, linking a policy, adding implementation notes, or marking a control implemented - adding evidence to a control, and any change to that evidence's state — submitted, verified, rejected, or expired - an automated evidence check returning a new result - assessing or treating a risk - creating or completing a business continuity exercise - preparing or finishing a vendor assessment - adding an asset - starting or finishing an assessment There is no nightly recalculation. The number is event-driven, so it updates within moments of the action rather than on a schedule. Recalculation runs in the background — if a percentage looks stale immediately after a bulk change, refresh the page after a few seconds. Raising Your Percentage In rough order of return on effort: 1. Look for empty sections first. Recording a handful of vendors or a single infrastructure asset can move the overall number several points, because each section carries a fixed 10-20% share. 2. Finish acknowledgement rounds. A published document sits at 30% until assignments go out and people respond. Chasing the last few acknowledgements converts 30% into 100% for that document. 3. Verify evidence rather than leaving it submitted. Submitted evidence scores 50%; verified scores 100%. For automated sources, a passing check gets you to 100% without manual review. 4. Mark genuinely irrelevant controls as not applicable. This scores them as complete in the Controls section and removes them from the Evidence section. 5. Assess risks you have already identified. An identified-but-unassessed risk scores zero; assessing it scores full. 6. Complete a business continuity exercise. A planned exercise is worth 50%, a completed one 100%. Troubleshooting "My evidence percentage is lower than I expected, but my sub-controls all have evidence." Check whether evidence is attached to parent controls that have structural sub-controls beneath them. Those parents are not measured; their sub-controls are. Also check for sub-controls with no evidence at all — a single uncovered control scores zero and pulls the average down more than a partially covered one. "I marked controls as not applicable and nothing changed." Not-applicable controls score 100% in the Controls section and are removed from the Evidence section. If neither number moved, confirm the status saved and that the controls belong to a section that is in scope. "Two of my projects show the same score for risks and vendors." That is expected. Those sections are account-wide. See "Three Rules That Surprise People" above. "The number did not change after I did the work." Recalculation is queued in the background rather than run on the spot. Give it a few seconds and reload. If it still has not moved, the item you changed may not affect a scored state — for example, editing the description of an already-implemented control does not change its score, because it is already at 100%.

MCP Server — Files, Limits, and Errors

This is the third part of the MCP server guide. Part 1 is https://help.auditbadger.com/hc/auditbadger-help-center/articles/1775898378-mcp-server-connect-ai-assistants-to-humadroid — tokens, scopes, delegation, and client setup. Part 2 is https://help.auditbadger.com/hc/auditbadger-help-center/articles/1788254081-mcp-server-tools-review-flow-and-limits — what the assistant can read and propose, and how a proposal becomes a change. This page is the reference an assistant works against once it is doing real work: how a file reaches a proposal, what the server will not let it do too often, what each error code means, and how you hear that a proposal is waiting. Attaching files An assistant can attach a screenshot or a PDF to evidence, or a SOC 2 report to a vendor assurance review. The flow is four steps: 1. request_upload_url — the assistant declares the filename, content type, byte size, and SHA-256 checksum. It gets back a staged_upload_id, a source_ref, and a PUT target on AuditBadger's own host: a url, the method, empty fields, and the headers to send. The capability is valid for 5 minutes, so have the file ready before calling. 2. PUT the bytes to that URL as the raw request body, with the returned headers and nothing else. The capability is bound to the exact byte size, SHA-256, and content type declared, so the file that arrives is the file that was described; anything else is refused on the spot, with the same reasons complete_staged_upload uses. 3. complete_staged_upload — AuditBadger verifies the checksum, sniffs the real content type from the bytes rather than trusting the name, neutralizes the content, and seals it. 4. Bind it by passing staged_upload_ids on the proposal, together with the source_ref from step 1 in the item's source_refs. Which operation an upload may be attached to is decided then, against that operation's own scopes. Replacing a file. On draft evidence, evidence.update takes staged_upload_ids to add files and remove_attachment_ids to delete files; send both in one proposal to replace a file. operation_companion for evidence.update lists the current files with their ids. Evidence that is submitted or verified does not change in place: propose a new version with evidence.create and parent_evidence_id. Automated evidence and historical versions do not change in place either, and they take no new version from an assistant: the collector versions automated evidence, and a historical version is replaced by the current one. The upload goes to AuditBadger, not to an object store. The url is on the same host as the MCP endpoint, so an assistant that can reach these tools can reach it, and nothing extra needs allowlisting. It carries its own authority: no bearer, session, or extra header is needed, which is what lets a sandboxed assistant, or a person acting for one, send the bytes. If the assistant cannot send bytes itself, it can hand a person one command and continue once it has run: curl -X PUT -H "Content-Type: application/pdf" --data-binary @report.pdf "<url>" A 204 means the bytes are in place; call complete_staged_upload next. A 401 means the five-minute window passed or the URL was altered; request a new one. A 422 names the mismatch. A 503 is the object store; PUT again. Retrying complete_staged_upload. When it answers retryable: true (upload_storage_unavailable, upload_scan_unavailable), call it again with the same idempotency_key. The first call reserved the upload for that key; a retry under a new key is refused as upload_invalid with reason completion_reserved. When it answers upload_invalid, the reason says which check failed and guidance what to do — for every reason but completion_reserved the staged upload is finished and the fix is a new request_upload_url; next_action says which: - object_missing — nothing arrived at the upload URL. The PUT did not complete; upload again. - size_mismatch / checksum_mismatch — the stored bytes are not the file that was declared. Declare the exact size and SHA-256 of the file you PUT. - content_type_mismatch — the bytes are not the declared type, or the type is not allowed. - capability_expired — the five-minute window passed, or the upload was already completed or bound. Replaying request_upload_url with the original idempotency_key after the window answers this too, rather than handing back the dead URL; request again under a new key. - completion_reserved — a retry under a different idempotency_key; replay the original one instead. - object_version_missing — the store returned no immutable version for the file. Upload again; if it recurs, report it with send_feedback. Provenance. The source_ref from request_upload_url is the one reference AuditBadger verifies itself: its content_sha256 is the checksum completion checks against the uploaded bytes, and binding requires that exact reference on the item. Pass it through unchanged. Allowed types: PNG, JPEG, GIF, WebP, and PDF. Nothing else. Stricter than ordinary evidence upload on purpose: every extra format is another parser. SVG is excluded despite being an image, because it is a document format that executes script. Size: 10 MB per file, up to 10 uploads and 50 MB per change set. Content neutralization happens on every file: - A PDF is refused if its bytes carry a name that brings active content — script, open or page actions, launch actions, embedded files, rich media, XFA forms — or encryption, which could hide any of those. You get upload_active_content. Send a flattened PDF. - An image is decoded and written back in the same format with every metadata block dropped: EXIF, ICC, XMP, comments, and anything appended after the image data. A rotated photo stays upright because orientation is applied before it is stripped; an animated image keeps its first frame. If re-encoding pushes it past 10 MB you get upload_neutralized_too_large. Uploads are not scanned for malware today. Neutralization is what stands in for it, and it cannot see inside a compressed PDF object stream. Scopes: an upload capability needs at least one <module>:propose scope for a module with an operation that accepts attachments — evidence and vendor assurance. A vendors-only token can upload the report it attaches; a controls-only token cannot upload at all, and gets token_scope_missing. Limits and errors Rate limits - 100 requests per minute per token. The bucket is keyed by a digest of the credential, never the credential itself. - 150 bearer-carrying requests per minute per IP address, across all tokens. This is what stops someone rotating bearer values to earn a fresh budget per guess. A team behind one shared egress address can reach it without any single token exceeding its own limit. - 20 requests per minute per IP for requests with no bearer header at all. - An IP that presents 30 rejected bearers within 10 minutes is banned for 30 minutes. A client still polling with a token you revoked can walk into this; fix the configuration and wait it out. Exceeding a throttle returns 429 with a Retry-After header. Authentication Every rejection is the same 401 with agent_token_required. It does not say whether the subdomain, the token, or the credential kind was wrong — deliberately, so the endpoint cannot be used to enumerate accounts. A valid REST API token lands here too, and gets the same 401: it authenticates elsewhere but is not valid for this surface. Check, in order: the subdomain in the URL, the token's expiry, whether it was revoked, whether your account still has API access enabled, and whether you are still an active member. Maintenance pauses If we pause the ingress for incident response, every request answers 503 headless_compliance_ingress_paused with retryable: true, a Retry-After: 60 header, and retry_after_seconds: 60 in the body. That tells a client to come back in a minute rather than re-authenticate or give up. Work already approved keeps applying. Error codes Errors are stable codes with a retryable flag and a next_action, so an assistant can act on them rather than parse prose. A refusal about the request itself also says where to look: item_position names the item (1-based), field is a JSON pointer into it (/params/owner_id, /observed_versions, /source_refs/2), and detail is one sentence about the rule it broke — so a 25-item set is fixed in one round rather than by bisection. Those three describe only what the assistant sent or what a read already returned to it; a domain refusal whose remedy is the assistant's — a subcontrol identifier that does not extend its parent, say — carries them too, and the rest stay a bare code. The ones you are most likely to see: - version_stale / version_required — the record moved, or the assistant did not send what it observed. next_action is repropose: read again and try once more. - token_scope_missing — the token lacks the module scope for that operation. Rotate with wider scopes, or narrow the task. - unauthorized — the sponsor cannot perform that action on that record. The agent inherits your permissions; it does not exceed them. - idempotency_key_reused — the same key with different content. A replay is fine; a second, different proposal needs a new key. - explicit_judgment_confirmation_required — delegated approval was asked to approve a judgment call. Open the review queue. - proposal_limit_reached — 20 open sets per token, 100 per account. Decide some. - control_cannot_hold_evidence — evidence was proposed on a criterion rather than a subcontrol beneath it. Only SOC 2 and HIPAA have criteria; ISO 27001 and the other frameworks list every control flat with criteria_root: false, and there is no hierarchy to walk. - upload_invalid — the staged upload failed a check; reason names it and guidance says what to do. See Attaching files. - source_refs_invalid — provenance was missing or malformed; field names the reference and detail the rule (https or urn without a query string, an explicitly zoned observed_at). - invalid_request — the request broke a structural rule; detail says which: an unknown field, a wrong type, compliance_project_id present on an account-scoped set or missing on a project-scoped one, an item mixing scopes, a subcontrol identifier that is not the parent identifier plus a numeric suffix (CC1.1.4 under CC1.1). - headless_compliance_ingress_unavailable — the pause above, seen from inside a tool result. One error arrives without any of these fields, because it comes from the MCP protocol layer before AuditBadger sees the request: -32602 Invalid params with Tool not found: <name> in data. The name is not a tool. If it is a read key from the catalogue in part 2, call read with that key; if it is an operation key or one of the tools removed on 2026-09-19, call propose with the operation_key. Arguments never fix this one, and some clients show only the first line. Workload limits A single change set holds at most 25 items, with dependency chains at most 5 deep and 10 wide. Each item may carry 10 source references and 256 KB of serialized content; a set may carry 50 references and 1 MB. Titles are capped at 200 characters, rationales and decision notes at 5,000. Lists page 50 at a time, 100 at most. Proposals expire 14 days after submission by default, and never later than 30 days. The assistant can read all of these from whoami rather than discovering them by failing. whoami also reports whether self-approval is enabled on the token, and both whoami and describe_operations give each operation its scope_kind (whether a set needs compliance_project_id) and approval_policy (explicit_judgment items are decided one by one by a person, so a set containing one is never approved through approve_change_set). Notifications and webhooks Seven lifecycle events are published, and both channels use the same list, so a subscription and a notification can never disagree about what exists: - agent.change_set_proposed - agent.change_set_decisions_finalized - agent.change_set_applied - agent.change_set_partially_applied - agent.change_set_failed - agent.change_set_cancelled - agent.change_set_expired Notifications reach reviewers by email by default, linking straight to the review page. Each person tunes their own channels in notification preferences; in-app is selectable for the record it keeps, but nothing renders these in-app yet, so email is what a reviewer should rely on. Webhooks are configured in Account Settings and can be account-wide or filtered to a single compliance project. Payloads carry the change set's identity, event, revision, state, item count, and review path — not the proposal's content, so a webhook can wake an external orchestrator without leaking what was proposed. Delivery is durable: it retries, and a redelivered event produces neither a second notification nor a second agent turn. A webhook is the right way to build "propose overnight, review in the morning". Polling get_change_set works too, and is simpler if the assistant is already running.