OpenCreds
Status: 0.1 draft · reference implementation available (@logicsrc/opencreds)
Slug: opencreds
OpenCreds is a LogicSRC OpenSpec for credential records and portable vaults. It defines what a credential item is, how a vault is encrypted, and what a vault looks like as a file — so that moving a vault between two products is a supported operation rather than a plaintext CSV export.
It exists because leaving a password manager currently means writing every secret you own to disk in the clear, and losing whatever the spreadsheet had no column for.
- Full specification:
docs/opencreds/spec.md - Item model:
docs/opencreds/item-model.md - Cryptography:
docs/opencreds/crypto.md - Portable database:
docs/opencreds/database.md - Importing from other products:
docs/opencreds/interop.md - CLI:
docs/opencreds/cli.md - Conformance:
docs/opencreds/conformance.md - Security model:
docs/opencreds/security.md - FAQ:
docs/opencreds/faq.md
What it defines
One record, six types. Logins, cards, identities, notes, keys and accounts
are not six features — they are one record with a type and a named field
group. Everything the user typed lives inside a single encrypted blob, which is
what makes password history free: it is an array in that blob, encrypted by
construction rather than needing its own protected table.
{
"v": 1,
"id": "6f1e7b3a-1f4e-4f0f-9a1d-6a2f0b6f8d21",
"type": "login",
"name": "GitHub",
"folderId": null,
"notes": "",
"login": {
"username": "anthony",
"password": "…",
"totp": "otpauth://totp/GitHub:anthony?secret=…",
"uris": [{ "uri": "https://github.com", "match": "domain" }]
},
"history": [],
"createdAt": "2026-08-29T00:00:00.000Z",
"updatedAt": "2026-08-29T00:00:00.000Z"
}
One envelope. AES-256-GCM over that JSON, with the item id bound in as additional authenticated data. A ciphertext moved from one row to another fails to decrypt rather than quietly showing the wrong credential — without that, anyone with database write access could swap a low-value login's ciphertext into a high-value one and watch what the user does next.
One key hierarchy. The master password is stretched once by PBKDF2-SHA256 into a master key, and everything else is derived from it by HKDF with a distinct label. The only password-derived value that ever reaches a server comes out of a different label than the wrapping key, so holding it does not help decrypt anything.
One file. A vault exports as a single .opencreds JSON document, encrypted
by default, carrying a manifest — item count, type histogram, digest over the
item ids — that is authenticated by the same tag as the data. A truncated
import fails instead of looking like a complete one.
What it does not define
Sync. Storage. Autofill. A conforming vault is a file and a key; how two devices reconcile, where the ciphertext lives, and how a browser fills a form are all left to the implementation.
Implementations
| Implementation | Profile | Namespace | Notes |
|---|---|---|---|
@logicsrc/opencreds |
user, team |
opencreds |
Reference implementation; local store and CLI |
logicsrc credentials |
team |
opencreds |
.env secrets and SSH keys as key items |
@marksyncr/vault |
user |
marksyncr |
Pre-dates the spec; conformant via its declared namespace |
MarkSyncr's vault shipped before OpenCreds and has domain-separation labels
baked into every ciphertext already written. Labels cannot be edited — changing
one makes every existing vault undecryptable — so the spec carries the label
prefix as a declared per-vault namespace rather than mandating a single
string. See crypto.md.
Quick start
# Create a vault (asks for a master password; prints a recovery key once)
logicsrc vault init
# Add items
logicsrc vault add login --name GitHub --username anthony --url https://github.com
logicsrc vault add card --name "Visa ending 4242"
logicsrc vault add key --name "deploy key" --key-type ssh --file ~/.ssh/id_ed25519
# List (never prints secret values)
logicsrc vault list --type login
# Move the vault somewhere else, encrypted
logicsrc vault export --out vault.opencreds
logicsrc vault import vault.opencreds --dry-run
# Import from another product
logicsrc vault import bitwarden-export.csv --source bitwarden --dry-run
The same commands ship as the standalone opencreds binary, so
logicsrc vault validate and opencreds validate are the same contract.
Relationship to the other LogicSRC specs
- Credential Sharing (credential-sharing.md)
moves secrets between providers —
.env, Doppler, Railway, GitHub, SSH. It models a key/value pair and a sync plan. OpenCreds models the record and the vault file. Akeyitem is what a synced.enventry becomes when it is stored rather than moved. - OpenContext (opencontext.md) governs what an agent may read. An agent that resolves a context bundle may be entitled to one OpenCreds item and not the vault; the permission decision is OpenContext's, the record shape is OpenCreds'.
- OpenOntology (openontology.md) names the entities a
credential belongs to. An
accountitem'sprovideris an ontology entity, not a free string, where an ontology is in use.