doc/SECRETS-AWS-PROVIDER.md
Operational contract for the hosted aws_secrets_manager secret provider used by Paperclip Cloud.
aws_secrets_manager
with their own region, namespace, prefix, KMS key id, and tags) are managed
in the board UI under Company Settings → Secrets → Provider vaults. See
Provider Vaults for the operator
model and Provider Vaults API for
the routes. The bootstrap trust model in this document still applies — vault
config carries non-sensitive routing metadata only, never AWS credentials.The AWS provider has a chicken-and-egg boundary: Paperclip cannot use
company_secrets to unlock the AWS provider that stores those secrets. The
initial AWS trust must exist before the Paperclip server starts.
Allowed bootstrap locations:
AWS_PROFILE, AWS SSO/shared config, web
identity, container metadata, or instance metadata.Do not ask operators to paste AWS root credentials or long-lived IAM user access
keys into the Paperclip board UI. Do not store those bootstrap keys in
company_secrets.
Paperclip Cloud must provision the AWS backing resources before any board user can create AWS-backed company secrets:
paperclipai doctor or the provider health endpoint from the deployed
runtime and confirm that the provider reports the expected region, prefix,
deployment id, KMS setting, and AWS SDK credential source.Once this is in place, the board UI can create Paperclip-managed AWS secrets and Paperclip will write them under the deployment/company namespace.
Self-hosted AWS deployments should use the AWS SDK default credential provider chain. Preferred sources are role-based:
AWS_PROFILE.Local development can use:
aws sso login --profile paperclip-dev
AWS_PROFILE=paperclip-dev \
PAPERCLIP_SECRETS_PROVIDER=aws_secrets_manager \
PAPERCLIP_SECRETS_AWS_REGION=us-east-1 \
PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID=dev-local \
PAPERCLIP_SECRETS_AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/abcd-... \
pnpm dev
Temporary AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY environment credentials
are acceptable only as a local break-glass or short-lived test source. They
should not be written to Paperclip config, committed to .env files, stored in
company_secrets, or used as the default Paperclip Cloud bootstrap path.
Required environment variables:
PAPERCLIP_SECRETS_PROVIDER=aws_secrets_manager
PAPERCLIP_SECRETS_AWS_REGION=us-east-1
PAPERCLIP_SECRETS_AWS_DEPLOYMENT_ID=prod-us-1
PAPERCLIP_SECRETS_AWS_KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/abcd-...
Optional environment variables:
PAPERCLIP_SECRETS_AWS_PREFIX=paperclip
PAPERCLIP_SECRETS_AWS_ENVIRONMENT=production
PAPERCLIP_SECRETS_AWS_PROVIDER_OWNER=paperclip
PAPERCLIP_SECRETS_AWS_ENDPOINT=
PAPERCLIP_SECRETS_AWS_DELETE_RECOVERY_DAYS=30
Naming convention for Paperclip-managed secrets:
paperclip/{deploymentId}/{companyId}/{secretKey}
Tag set for Paperclip-managed secrets:
paperclip:managed-by=paperclippaperclip:provider-owner=<owner tag>paperclip:deployment-id=<deployment id>paperclip:company-id=<company id>paperclip:secret-key=<secret key>paperclip:environment=<environment tag>Launch posture:
Minimum IAM boundary:
secretsmanager:CreateSecret, PutSecretValue, GetSecretValue, and DeleteSecret.arn:aws:secretsmanager:<region>:<account-id>:secret:paperclip/<deployment-id>/*
kms:Encrypt, kms:Decrypt, kms:GenerateDataKey, and kms:DescribeKey for the configured deployment CMK.Example minimum policy shape:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PaperclipDeploymentSecrets",
"Effect": "Allow",
"Action": [
"secretsmanager:CreateSecret",
"secretsmanager:PutSecretValue",
"secretsmanager:GetSecretValue",
"secretsmanager:DeleteSecret"
],
"Resource": "arn:aws:secretsmanager:<region>:<account-id>:secret:paperclip/<deployment-id>/*"
},
{
"Sid": "PaperclipDeploymentKms",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:<region>:<account-id>:key/<key-id>"
}
]
}
Operational expectation:
Remote import preview needs one additional AWS permission:
{
"Sid": "PaperclipRemoteSecretInventory",
"Effect": "Allow",
"Action": "secretsmanager:ListSecrets",
"Resource": "*"
}
This is intentionally separate from the managed create/rotate/delete policy.
AWS treats ListSecrets as an account/Region inventory action; do not document
secret ARNs, names, tags, or AWS request filters as an IAM boundary for it. Use
Resource: "*" and decide whether inventory exposure is acceptable for the AWS
account and Region behind each provider vault.
Remote import preview/import must not call:
secretsmanager:GetSecretValuesecretsmanager:BatchGetSecretValuekms:DecryptThose permissions are only needed later when a bound runtime resolves an imported external reference. For imported refs, scope read permissions to the operator-approved external prefixes that Paperclip is allowed to consume:
{
"Sid": "PaperclipResolveImportedExternalReferences",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": [
"arn:aws:secretsmanager:<region>:<account-id>:secret:<approved-external-prefix>/*"
]
}
If selected external secrets use customer-managed KMS keys, also grant
kms:Decrypt and kms:DescribeKey on those keys. Keep managed write/delete
permissions scoped to paperclip/<deployment-id>/*; do not broaden them for
remote import.
Safe scoping guidance:
ListSecrets only in accounts where inventory exposure is acceptable.Paperclip also blocks importing refs under its own managed namespace as
external references. Use the Paperclip-managed flow for
paperclip/{deploymentId}/{companyId}/{secretKey} resources.
V1 keeps existing AWS Secrets Manager entries as linked external references, not adopted Paperclip-managed resources.
Use the Paperclip-managed flow when Paperclip should create and rotate the value. The AWS secret name is derived from deployment and company scope:
paperclip/{deploymentId}/{companyId}/{secretKey}
Use the external-reference flow when the secret already exists at an operator-owned path such as:
/paperclip-bench/anthropic_api_key
In that mode Paperclip stores only the path or ARN, resolves it at runtime, and records redacted access events. Operators rotate the actual value in AWS. Update the Paperclip reference only when the AWS path, ARN, or pinned provider version changes.
Paperclip does not currently offer an "adopt existing AWS secret" flow that takes over future
PutSecretValue writes for an arbitrary existing secret. Adding that later requires explicit
confirmation UX, scope validation, expected Paperclip tags, and security/cloud-ops review.
externalRef, providerVersionRef, provider id, fingerprint hash, status, and binding metadata.company_secret_versions.material.Manual Paperclip-managed rotation:
PutSecretValue.providerVersionRef in company_secret_versions.latest, or pin consumers to a specific Paperclip version before rollout when you need staged release safety.Guidance:
What must survive:
Restore checklist:
GetSecretValue on the restored prefix.PAPERCLIP_SECRETS_AWS_KMS_KEY_ID.Symptoms:
Immediate actions:
GetSecretValue and KMS decrypt permissions.Remote import-specific actions:
secretsmanager:ListSecrets with
Resource: "*" only when inventory import is approved for that vault's
AWS account and Region.NextToken.GetSecretValue and KMS decrypt
on the selected external secret. Visibility in ListSecrets does not prove
read permission.Potential incidents:
Response steps:
ListSecrets, GetSecretValue,
PutSecretValue, and DeleteSecret calls on the relevant vault account,
Region, deployment prefix, and approved external prefixes.This is safe to skip locally. Run it only against a dedicated AWS test namespace.
Prerequisites:
PAPERCLIP_SECRETS_PROVIDER=aws_secrets_managerPAPERCLIP_SECRETS_AWS_* environment variables set.Suggested smoke:
paperclip/{deploymentId}/{companyId}/{secretKey}.providerVersionRef appears in Paperclip metadata.