|
UnENVerse 0.42.4
Local-first desktop secrets manager — TypeScript frontend
|
Data models for UnENVerse. More...
Variables | |
| export type | SecretType |
| Discriminated union of all supported secret kinds. | |
| export type | ValueKind |
The editor/validator/preview an extra_vars value gets (Phase 24.1). | |
| export type | RateLimitPeriod = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year' |
| A single stored secret entry. | |
| export interface | VaultEntry |
| provider | __pad0__ |
| Service or provider name (e.g. | |
| account_name | __pad1__ |
| Optional sub-account identifier within the same provider. | |
| api_key | __pad2__ |
| Primary secret value (API key, password, variable value, etc.). | |
| api_secret | __pad3__ |
| Secondary secret (client secret, shared secret). | |
| key_id | __pad4__ |
| Optional key identifier for disambiguation when one provider has multiple keys. | |
| api_description | __pad5__ |
| Short human-readable description of what the key is used for. | |
| description | __pad6__ |
| Longer free-text notes. | |
| price_type | __pad7__ |
| Billing model for the associated service. | |
| environment | __pad8__ |
| Deployment context this credential belongs to. | |
| categories | __pad9__ |
| Category tags this entry carries. | |
| api_url | __pad10__ |
| Base URL of the service's API. | |
| callback_url | __pad11__ |
| OAuth or webhook callback URL. | |
| expires_at | __pad12__ |
ISO-8601 expiry date string, or null if the credential does not expire. | |
| scopes | __pad13__ |
| OAuth scopes or permission strings granted to this credential. | |
| rate_limit | __pad14__ |
| Human-readable rate-limit description (e.g. | |
| rate_limit_count | __pad15__ |
The rate limit as a number, paired with rate_limit_period. | |
| rate_limit_period | __pad16__ |
The window rate_limit_count applies to. | |
| rate_limit_note | __pad17__ |
Whatever the old free-text rate_limit said when it could not be parsed into a count and a period ("varies by endpoint", "see contract"). | |
| purpose | __pad18__ |
| What this credential was requested for — the justification submitted to the issuer on the application form. | |
| pool | __pad19__ |
Name of the key pool this entry belongs to, or null for a standalone key. | |
| version | __pad20__ |
| API or SDK version this key was issued for. | |
| primary_role | __pad21__ |
What the primary value is, for naming purposes — the ROLE segment of the generated environment-variable name. | |
| secret_role | __pad22__ |
Role of api_secret, when the default SECRET is wrong. | |
| primary_public | __pad23__ |
The primary value is safe to print — an OAuth client id, a Stripe pk_, an AWS access key id. | |
| secret_public | __pad24__ |
The same, for api_secret. | |
| auth_scheme | __pad25__ |
| How this credential is sent (Phase 23, E16). | |
| auth_param | __pad26__ |
The header or query-parameter name auth_scheme puts the value in. | |
| auth_template | __pad27__ |
For header: the value sent, with {key} standing for the credential, e.g. | |
| user_agent | __pad28__ |
| The User-Agent this credential was minted against (Phase 23, step 5). | |
| last_verified_at | __pad29__ |
| When the user last confirmed this session still works (Phase 23, E13). | |
| storage_tokens | __pad30__ |
Storage tokens (localStorage/sessionStorage) a web session needs alongside its cookies (Phase 24.5). | |
| storage | __pad31__ |
| key | __pad32__ |
| value | __pad33__ |
| header_recipe | __pad34__ |
How a derived header is built for this session — the *arr family's X-Api-Key, YouTube's SAPISIDHASH, LinkedIn's csrf header copied off a cookie. | |
| source | __pad35__ |
| static_value | __pad36__ |
| cookie_name | __pad37__ |
| strip_quotes | __pad38__ |
| derived_id | __pad39__ |
| acts_as | __pad40__ |
API-key taxonomy — orthogonal axes (Phase 24.5), auto-filled from issuer prefixes by enrich (gaps only, per the existing rule) and never enforced: ‘exposure: 'publishable’*suggests*primary_public`, never sets it, so a misdetected prefix cannot make redaction print less. | |
| reach | __pad41__ |
| exposure | __pad42__ |
| issuer_kind | __pad43__ |
| access | __pad44__ |
| console_url | __pad45__ |
| Where to revoke or rotate this credential. | |
| ip_allowlist | __pad46__ |
| last_copied_name | __pad47__ |
| The generated variable name this entry was last copied or exported under (Phase 23, step 6). | |
| blob_data | __pad48__ |
| The contents of a file-shaped credential (Phase 23, E17). | |
| mount_path | __pad49__ |
| Where the consumer expects to find this credential on disk (E17). | |
| composite_template | __pad50__ |
The shape of a composite entry's rendered value, holes and all — https://.../{mailbox_id}@.../{calendar_key}/calendar.ics. | |
| composite_kind | __pad51__ |
What kind of thing a composite template is, which decides its encoding and whether Open is offered. | |
| bundle_id | __pad52__ |
| The bundle entry's id this entry is a member of (Phase 24.1). | |
| bundle_slot | __pad53__ |
This member's slot name within its bundle — "discord", "web", "v3". | |
| bundle_order | __pad54__ |
| Sort key with gaps, never identity (invariant 1) — the same shape as a pool cursor position, not an array index. | |
| bundle_primary | __pad55__ |
On the bundle entry itself (‘secretType === 'bundle’): which member's id the card's main Copy button copies. | |
| label | __pad56__ |
A short namespace token inserted into generated environment-variable names after the version — SPOTIFY_V2_GAME_ID. | |
| custom_icon | __pad57__ |
Simple Icons slug for a custom provider icon, or null to use auto-detection. | |
| details | __pad58__ |
| Additional metadata or usage notes. | |
| version_history | __pad59__ |
Snapshots of previous api_key values. | |
| saved_at | __pad60__ |
| projectIds | __pad61__ |
| Ids of the projects this entry belongs to. | |
| secretType | __pad62__ |
| Discriminates which secret-type-specific fields and form layout apply. | |
| username | __pad63__ |
Username for password or ssh_key entries. | |
| __pad64__ | |
| Email associated with this credential. | |
| certificate_data | __pad65__ |
| PEM-encoded certificate content (fullchain). | |
| cert_key_data | __pad66__ |
| Private key PEM paired with this certificate. | |
| cert_issuer | __pad67__ |
| Issuer / CA that provided the certificate (e.g. | |
| blob_ref | __pad68__ |
| File-system path or reference to a credential file. | |
| env_var_subtype | __pad69__ |
| Sub-type hint for env_var entries (used for display and filtering). | |
| created_at | __pad70__ |
| ISO-8601 timestamp of when this entry was first written to the vault. | |
| last_rotated_at | __pad71__ |
| ISO-8601 timestamp of the last manual rotation (set via "Mark as rotated"). | |
| rotation_days | __pad72__ |
| Rotation cadence in days. | |
| compromised | __pad73__ |
| Marks a credential as known-leaked / emergency-rotate. | |
| tags | __pad74__ |
| Free-form tags for quick cross-cutting labelling (separate from categories/projects). | |
| pinned | __pad75__ |
| When true the entry floats to the top of all filtered views. | |
| extra_vars | __pad76__ |
| Extra named fields beyond the fixed schema (e.g. | |
| value | __pad77__ |
| secret | __pad78__ |
| __pad79__ | |
| Opt this value out of redaction everywhere (Phase 23, E5). | |
| role | __pad80__ |
Overrides the env-name segment derived from key (Phase 23 design, finally added in 24.1 alongside composite parts — a part's placeholder name and its generated env-name segment are not always the same word). | |
| tier | __pad81__ |
| Which copy profile includes this variable. | |
| kind | __pad82__ |
| The editor/validator/preview this value gets in the form (Phase 24.1). | |
| attrs | __pad83__ |
| Per-cookie attributes, filled by the paste parser (Phase 23, E14). | |
| path | __pad84__ |
| secure | __pad85__ |
| http_only | __pad86__ |
| expires | __pad87__ |
| Unix seconds. | |
| totp_secret | __pad88__ |
| Base32 TOTP seed this credential's service issued — the authenticator secret, from which UnENVerse generates the six digits you type into that service's login form. | |
| totp_algorithm | __pad89__ |
| HMAC the issuer generates with. | |
| totp_digits | __pad90__ |
| Digits in the generated code. | |
| totp_period | __pad91__ |
| Seconds a code is valid for. | |
| totp_kind | __pad92__ |
What the seed is: totp (time-based, the default when absent), hotp (counter-based) or steam (Steam Guard's five characters). | |
| totp_counter | __pad93__ |
The next counter an hotp seed will use. | |
| env_prefixes | __pad94__ |
| Env-var prefixes added by services that consume this credential. | |
| export interface | Project |
| A hierarchical category node (UI label: "Category"). | |
| name | __pad95__ |
| Display name. | |
| description | __pad96__ |
| Optional description shown as a tooltip in the category tree. | |
| project_type | __pad97__ |
| High-level type of the project — drives the special config view. | |
| chunks | __pad98__ |
| Structured config chunks for WireGuard or Docker projects. | |
| export type | ChunkFieldType |
| Sub-type of a field in a structured config chunk. | |
| export interface | ChunkField |
| A single field within a structured config chunk (WireGuard section, Docker service, etc.). | |
| value | __pad99__ |
| Raw value or "${REF_NAME}" syntax to reference a vault env_var entry. | |
| field_type | __pad100__ |
| How this field is categorised and exported. | |
| ref_name | __pad101__ |
If non-null, this field's value is resolved from the vault entry where provider === ref_name and ‘secretType === 'env_var’`. | |
| secret | __pad102__ |
| When true the value is masked in the UI. | |
| description | __pad103__ |
| Optional description / comment for this field. | |
| export type | ChunkType |
| Type of a structured config chunk — determines field schema and export format. | |
| export interface | SecretChunk |
| A named section within a structured project config. | |
| name | __pad104__ |
| Display name ("Interface", "Peer — office", "navidrome service", etc.). | |
| chunk_type | __pad105__ |
| fields | __pad106__ |
| notes | __pad107__ |
| Optional freetext notes shown under the chunk header. | |
| disabled | __pad108__ |
| When true the chunk is greyed-out and excluded from exports. | |
| last_copied_snapshot | __pad109__ |
| Snapshot of resolved env output (KEY→value hash map) at last copy — powers "changed since last copy". | |
| last_copied_snapshot | string |
| last_copied_at | __pad110__ |
| ISO-8601 timestamp of the last resolved copy. | |
| export type | ProjectType |
| High-level type of a project — drives the special config view. | |
| export const | STABLE_PROJECT_TYPES |
| Project types that have actually been exercised end to end. | |
| export const | wireguard |
| export const | docker |
| export const | nginx |
| export const | kubernetes |
| export const | ssh_config |
| export const | traefik |
| export const | apache |
| export const | haproxy |
| export const | ansible |
| export const | postgres |
Data models for UnENVerse.
@description Defines the structure of vault entries, projects, and application settings shared between the TypeScript frontend and the persisted JSON format. These types mirror the JSON blob stored in the SQLCipher vault table.
| export type SecretType |
Discriminated union of all supported secret kinds.
The active variant controls which form fields are shown and which card labels are used. api_key is the default for legacy entries.
api_key – Standard API key or bearer token.password – Service login password.certificate – PEM-encoded TLS/SSL certificate.env_var – Shell environment variable (name + value pair).connection_string – Database or service connection URI.ssh_key – SSH private key or host fingerprint.file_blob – Reference path to an on-disk credential file. | export type ValueKind |
The editor/validator/preview an extra_vars value gets (Phase 24.1).
Never a storage change — see the field doc on extra_vars[].kind. Core, colour, template and large-id/bitfield groups landed in 24.1 (the Discord acceptance fixture needs them); the dev-format group is deferred to 24.5, where it lands beside the secret-type registry the descriptors belong to.
A single stored secret entry.
api_key holds the primary secret value regardless of secretType. Fields irrelevant to a given type are null / undefined and hidden in the UI. Every entry always belongs to at least the "Universal" category (projectIds). The window a VaultEntry.rate_limit_count applies to.
second and minute are here even though most published limits are hourly or daily, because the ones that bite in practice are per-second burst caps — and because the free-text values already in vaults are overwhelmingly "n/min", which has to survive migration as something.
| export interface VaultEntry |
| provider __pad0__ |
Service or provider name (e.g.
"GitHub", "DATABASE_URL"). Always required.
| account_name __pad1__ |
Optional sub-account identifier within the same provider.
| api_key __pad2__ |
Primary secret value (API key, password, variable value, etc.).
| api_secret __pad3__ |
Secondary secret (client secret, shared secret).
Used by api_key type only.
| key_id __pad4__ |
Optional key identifier for disambiguation when one provider has multiple keys.
| api_description __pad5__ |
Short human-readable description of what the key is used for.
| description __pad6__ |
Longer free-text notes.
| price_type __pad7__ |
Billing model for the associated service.
| environment __pad8__ |
Deployment context this credential belongs to.
| categories __pad9__ |
Category tags this entry carries.
Backed by VaultData.user_categories, shown in the sidebar's "Categories" section, and matched by RBAC scope_type: "category".
(An earlier comment here claimed these were labelled "Projects" in the UI. They are not — the data names, the sidebar headings and the RBAC scope names all agree. Only the DOM element ids were crossed, and those have since been renamed.)
| api_url __pad10__ |
Base URL of the service's API.
| callback_url __pad11__ |
OAuth or webhook callback URL.
| expires_at __pad12__ |
ISO-8601 expiry date string, or null if the credential does not expire.
| scopes __pad13__ |
OAuth scopes or permission strings granted to this credential.
| rate_limit __pad14__ |
Human-readable rate-limit description (e.g.
"100 req/min").
Legacy, and kept deliberately. The structured pair below (rate_limit_count + rate_limit_period) is what the UI and the health scan read. This string is still written on save, rendered from the pair when the pair is set, so a vault edited by a current build stays readable to an older one — and so an entry whose limit was never expressible as <n> per <period> ("varies by endpoint") keeps the text the user wrote.
Never parse this field directly. parseRateLimit() in utils.ts is the one reader, and unv-cli/src/ratelimit.rs is its twin.
| rate_limit_count __pad15__ |
The rate limit as a number, paired with rate_limit_period.
null means "not known", which is not the same as 0 — a limit of zero would mean the credential is useless, and some services really do issue suspended keys. Both halves must be set for the limit to be considered structured; a count without a period is meaningless and is dropped on read.
| rate_limit_period __pad16__ |
The window rate_limit_count applies to.
| rate_limit_note __pad17__ |
Whatever the old free-text rate_limit said when it could not be parsed into a count and a period ("varies by endpoint", "see contract").
Kept rather than discarded: the text was written by a human who knew something the schema does not express, and silently dropping it on the first save under a new version is data loss the user never asked for.
| purpose __pad18__ |
What this credential was requested for — the justification submitted to the issuer on the application form.
Distinct from api_description (what it is) and details (notes to self). This is the sentence you will be held to if the issuer asks why you have the key, and it is worth recording at the moment you write it, because six months later nobody remembers.
| pool __pad19__ |
Name of the key pool this entry belongs to, or null for a standalone key.
Several entries sharing a pool name are interchangeable credentials for the same service, held so that a caller can swap between them when one is rate limited. Membership is explicit: two keys for the same provider do not pool automatically, because unv get GitHub refusing an ambiguous match is the behaviour that stops a command from silently acting on a credential the caller did not mean (see the invariants in CLAUDE.md).
Swap state — cursor, cooldowns, use counts — is deliberately NOT stored here. It lives in a per-machine sidecar; see unv-cli/src/pool.rs.
| version __pad20__ |
API or SDK version this key was issued for.
| primary_role __pad21__ |
What the primary value is, for naming purposes — the ROLE segment of the generated environment-variable name.
Absent keeps the bare name. Every .env already deployed from this app names the primary value PROVIDER=, so defaulting this to ‘'key’` would rename that variable for every existing entry on the next copy, and the user would find out when a service came back up without its credentials.
The vocabulary is open, not a closed union past the six presets: issuers invent names (app_id, merchant_id, tenant), and a closed union means the escape hatch is extra_vars — which is the fragmentation Phase 23 exists to remove.
| secret_role __pad22__ |
Role of api_secret, when the default SECRET is wrong.
| primary_public __pad23__ |
The primary value is safe to print — an OAuth client id, a Stripe pk_, an AWS access key id.
Opts api_key out of redaction everywhere (E5).
| secret_public __pad24__ |
The same, for api_secret.
Rare, but an issuer's "secret" is sometimes public.
| auth_scheme __pad25__ |
How this credential is sent (Phase 23, E16).
How to send it is part of the credential and was nowhere in the model: two entries that look identical are used completely differently, and the user had to remember which service wants X-Api-Key, which wants Authorization: Bearer, and which wants it in the query string.
This is what turns a stored string into a working request, and it is what the curl and cookie exports need anyway.
| auth_param __pad26__ |
The header or query-parameter name auth_scheme puts the value in.
Meaningless for bearer (the header is fixed) and for basic (the value is the password half). Defaults to X-Api-Key for header and api_key for query.
| auth_template __pad27__ |
For header: the value sent, with {key} standing for the credential, e.g.
MediaBrowser Token="{key}". Absent means the credential on its own.
| user_agent __pad28__ |
The User-Agent this credential was minted against (Phase 23, step 5).
A session cookie replayed without the matching User-Agent usually 401s, so this is not optional metadata — it is half of the credential.
It is also a fingerprint, so it never appears in basic metadata comments or anywhere the redacting resolver writes.
| last_verified_at __pad29__ |
When the user last confirmed this session still works (Phase 23, E13).
Rotation is meaningless for a session credential — "rotate" means "log in again in a browser", which this app cannot do — so a cookie flagged never-rotated and overdue forever is a nag with no available fix, and a nag with no available fix trains people to ignore the health scan, which costs more than it gains. This is the check that is actionable instead.
| storage_tokens __pad30__ |
Storage tokens (localStorage/sessionStorage) a web session needs alongside its cookies (Phase 24.5).
cookie generalises from "a cookie
jar" to "a web session" without a field rename — every Phase 23 vault still uses the cookie id, only the label reads "Web session" now.
Never in basic metadata or a redacting resolver's output — a storage token is exactly as much a live credential as the cookies beside it.
| storage __pad31__ |
| key __pad32__ |
| value __pad33__ |
| header_recipe __pad34__ |
How a derived header is built for this session — the *arr family's X-Api-Key, YouTube's SAPISIDHASH, LinkedIn's csrf header copied off a cookie.
‘source: 'derived’` headers are computed at copy time, so a copied header is only good briefly; the UI that renders one says so.
| source __pad35__ |
| static_value __pad36__ |
| cookie_name __pad37__ |
| strip_quotes __pad38__ |
| derived_id __pad39__ |
| acts_as __pad40__ |
API-key taxonomy — orthogonal axes (Phase 24.5), auto-filled from issuer prefixes by enrich (gaps only, per the existing rule) and never enforced: ‘exposure: 'publishable’*suggests*primary_public`, never sets it, so a misdetected prefix cannot make redaction print less.
| reach __pad41__ |
| exposure __pad42__ |
| issuer_kind __pad43__ |
| access __pad44__ |
| console_url __pad45__ |
Where to revoke or rotate this credential.
| ip_allowlist __pad46__ |
| last_copied_name __pad47__ |
The generated variable name this entry was last copied or exported under (Phase 23, step 6).
The only new persisted state this phase adds, and it exists for one finding: renaming a provider, version or label silently renames every variable the entry generates, and the .env already sitting on a server keeps the old name. That is the renameProviderRefs() problem with a wider blast radius, because the stale reference is not in the vault at all — it is in a file on a machine nobody is looking at.
Non-secret: a variable name is not a credential.
| blob_data __pad48__ |
The contents of a file-shaped credential (Phase 23, E17).
A GCP service-account JSON, an Apple .p8, an mTLS bundle and a kubeconfig are consumed by pointing at them: GOOGLE_APPLICATION_CREDENTIALS=/etc/gcp/sa.json. Copying the contents to a clipboard produces something no consumer wants, and pasting a 2 KB JSON blob into a .env produces a variable the library tries to open as a path.
blob_ref holds only a path, so a fresh machine has the reference and not the credential; certificate_data holds the PEM but has nowhere to write it. This is the storage half, and mount_path is the delivery half.
Capped — see BLOB_MAX_BYTES. A service-account JSON is ~2.3 KB and an embedded icon is already allowed 96 KB, so storing content is fine; a kubeconfig with several clusters or a full chain bundle is not the same promise, and silently storing a truncated credential is worse than refusing.
| mount_path __pad49__ |
Where the consumer expects to find this credential on disk (E17).
The delivery half of a file-shaped entry: unv file write materialises to it, ${Entry/path} renders it, and unv exec writes a temp file and removes it afterwards. Non-secret — it is a path, not a credential.
| composite_template __pad50__ |
The shape of a composite entry's rendered value, holes and all — https://.../{mailbox_id}@.../{calendar_key}/calendar.ics.
Printed, not masked (it is the holes, not the values) — it must still be added to PUBLIC_FIELDS deliberately, since fail-closed redaction would otherwise mask it. See src/ts/composite.ts for rendering.
| composite_kind __pad51__ |
What kind of thing a composite template is, which decides its encoding and whether Open is offered.
Open past the four presets — the same open-vocabulary reasoning as primary_role.
| bundle_id __pad52__ |
The bundle entry's id this entry is a member of (Phase 24.1).
Membership is stored once, on the member — the same shape as pool — so an older build that deletes the bundle entry cannot leave two disagreeing copies of "is this bundled". null/absent means unbundled.
| bundle_slot __pad53__ |
This member's slot name within its bundle — "discord", "web", "v3".
Validated like label (^[A-Za-z0-9][A-Za-z0-9_-]{0,23}$), unique within the bundle. Addressed as ${bundle:Name/slot} and {slot.field} inside the bundle's own templates.
| bundle_order __pad54__ |
Sort key with gaps, never identity (invariant 1) — the same shape as a pool cursor position, not an array index.
| bundle_primary __pad55__ |
On the bundle entry itself (‘secretType === 'bundle’): which member's id the card's main Copy button copies.
null` means nothing is copyable from the collapsed card yet.
| label __pad56__ |
A short namespace token inserted into generated environment-variable names after the version — SPOTIFY_V2_GAME_ID.
Not account_name. Account names in real vaults are email addresses, and SPOTIFY_DARTHDEMONO_GMAIL_COM_ID is not what anyone wants. Validated at the form to ^[A-Za-z0-9][A-Za-z0-9_-]{0,23}$ so it is always usable as a segment.
| custom_icon __pad57__ |
Simple Icons slug for a custom provider icon, or null to use auto-detection.
| details __pad58__ |
Additional metadata or usage notes.
| version_history __pad59__ |
Snapshots of previous api_key values.
Prepended automatically on save when the value changes.
| saved_at __pad60__ |
| projectIds __pad61__ |
Ids of the projects this entry belongs to.
Backed by VaultData.projects, shown in the sidebar's "Projects" section, and matched by RBAC scope_type: "project".
Always contains "Universal" — the catch-all every entry carries. A specific project grant is never satisfied by it.
| secretType __pad62__ |
Discriminates which secret-type-specific fields and form layout apply.
| username __pad63__ |
Username for password or ssh_key entries.
| email __pad64__ |
Email associated with this credential.
| certificate_data __pad65__ |
PEM-encoded certificate content (fullchain).
certificate entries only.
| cert_key_data __pad66__ |
Private key PEM paired with this certificate.
| cert_issuer __pad67__ |
Issuer / CA that provided the certificate (e.g.
"Let's Encrypt", "Google", "EnvV"). certificate entries only.
| blob_ref __pad68__ |
File-system path or reference to a credential file.
file_blob entries only.
| env_var_subtype __pad69__ |
Sub-type hint for env_var entries (used for display and filtering).
| created_at __pad70__ |
ISO-8601 timestamp of when this entry was first written to the vault.
Optional because vaults written before this field existed have no such record, and there is no honest way to invent one. backfillCreatedAt() in state.ts infers a date for those from evidence already in the vault — the oldest version_history snapshot, or the earliest audit row naming the entry — and leaves it unset when there is none. An entry with no created_at renders as "unknown" and is omitted from the calendar feed, which is the truthful answer: stamping "today" onto every pre-existing secret would make the timeline panel and every exported .ics repeat a date nobody chose.
Never rewritten on edit. This is a creation date, not a modification date; version_history[0].saved_at is where "when did it last change" lives.
| last_rotated_at __pad71__ |
ISO-8601 timestamp of the last manual rotation (set via "Mark as rotated").
| rotation_days __pad72__ |
Rotation cadence in days.
When set, health scan flags entries overdue since last_rotated_at.
| compromised __pad73__ |
Marks a credential as known-leaked / emergency-rotate.
Surfaces as a critical health issue.
| tags __pad74__ |
Free-form tags for quick cross-cutting labelling (separate from categories/projects).
| pinned __pad75__ |
When true the entry floats to the top of all filtered views.
| extra_vars __pad76__ |
Extra named fields beyond the fixed schema (e.g.
db, port, host for database entries).
| value __pad77__ |
| secret __pad78__ |
| __pad79__ |
Opt this value out of redaction everywhere (Phase 23, E5).
extra_vars are masked by default. public is per value and never per type: a client id, a region, an account SID and a publishable key are each safe to print and the secret beside them is not. Without it the basic copy profile is either useless (everything masked) or unsafe (nothing).
| role __pad80__ |
Overrides the env-name segment derived from key (Phase 23 design, finally added in 24.1 alongside composite parts — a part's placeholder name and its generated env-name segment are not always the same word).
| tier __pad81__ |
Which copy profile includes this variable.
Absent means ‘'basic’`.
| kind __pad82__ |
The editor/validator/preview this value gets in the form (Phase 24.1).
Storage never changes: every value is a string end to end, whatever the kind. A kind is data about how to edit the string, never a coercion — hex_int and large_id both stay strings so a JSON export can quote a large id without a JS number silently rounding it.
| attrs __pad83__ |
Per-cookie attributes, filled by the paste parser (Phase 23, E14).
cookies.txt needs a domain, an include-subdomains flag, a path, a secure flag and an expiry for every cookie. A DevTools "Copy all as JSON" and a pasted cookies.txt both carry them; a bare document.cookie string does not, and the export is refused in that case rather than writing a file yt-dlp silently ignores.
| path __pad84__ |
| secure __pad85__ |
| http_only __pad86__ |
| expires __pad87__ |
Unix seconds.
0 is a session cookie.
| totp_secret __pad88__ |
Base32 TOTP seed this credential's service issued — the authenticator secret, from which UnENVerse generates the six digits you type into that service's login form.
This is the reverse of the Phase 19 TOTP, which is a second factor on UnENVerse's own sub-user login and lives in the users table, never here. Nothing reads both.
Stored normalised: uppercase base32, no spaces, dashes or padding, so two entries holding the same seed typed differently are byte-identical and fingerprint the same. A pasted otpauth:// URI is split into this field and the three below at the form rather than stored whole — the URI is a container, and keeping it would mean a second field that also holds the secret and has to be masked everywhere this one is.
It is a secret in every sense the vault means: masked by maskKeysByDefault, in SECRET_FIELDS for CLI redaction, and snapshot into version_history on change.
| totp_algorithm __pad89__ |
HMAC the issuer generates with.
Absent means SHA-1, which is what otpauth:// means when it omits the parameter and what almost every issuer uses. Written only when the issuer said something else — a field that reads "SHA1" on every entry cannot be told apart from a defaulted one.
| totp_digits __pad90__ |
Digits in the generated code.
Absent means 6.
| totp_period __pad91__ |
Seconds a code is valid for.
Absent means 30.
| totp_kind __pad92__ |
What the seed is: totp (time-based, the default when absent), hotp (counter-based) or steam (Steam Guard's five characters).
Phase 22.2.
| totp_counter __pad93__ |
The next counter an hotp seed will use.
Written whenever the seed is counter-based, zero included — zero is a real position, not an absent one — and removed for the other kinds. It is state rather than configuration, which is why advancing it is an explicit action.
| env_prefixes __pad94__ |
Env-var prefixes added by services that consume this credential.
For Key type: e.g. ["ND", "SPOTIFYD"] means Navidrome uses ND_LASTFM_APIKEY. For Chunk type: the first prefix IS the chunk's env-namespace identifier (e.g. ["AM"] for AM_JWT_SECRET).
| export interface Project |
A hierarchical category node (UI label: "Category").
Slash-delimited names encode a virtual tree: "Cloud/AWS" is a child of "Cloud". The reserved entry with id === "Universal" is a catch-all; every entry belongs to it.
| name __pad95__ |
Display name.
Slash-segments indicate hierarchy (e.g. "Cloud/AWS").
| description __pad96__ |
Optional description shown as a tooltip in the category tree.
| project_type __pad97__ |
High-level type of the project — drives the special config view.
| chunks __pad98__ |
Structured config chunks for WireGuard or Docker projects.
| export type ChunkFieldType |
Sub-type of a field in a structured config chunk.
| export interface ChunkField |
| value __pad99__ |
Raw value or "${REF_NAME}" syntax to reference a vault env_var entry.
| field_type __pad100__ |
How this field is categorised and exported.
| ref_name __pad101__ |
If non-null, this field's value is resolved from the vault entry where provider === ref_name and ‘secretType === 'env_var’`.
| secret __pad102__ |
When true the value is masked in the UI.
| description __pad103__ |
Optional description / comment for this field.
| export type ChunkType |
Type of a structured config chunk — determines field schema and export format.
| export interface SecretChunk |
A named section within a structured project config.
| name __pad104__ |
Display name ("Interface", "Peer — office", "navidrome service", etc.).
| chunk_type __pad105__ |
| fields __pad106__ |
| notes __pad107__ |
Optional freetext notes shown under the chunk header.
| disabled __pad108__ |
When true the chunk is greyed-out and excluded from exports.
| last_copied_snapshot __pad109__ |
Snapshot of resolved env output (KEY→value hash map) at last copy — powers "changed since last copy".
| last_copied_snapshot string |
| last_copied_at __pad110__ |
ISO-8601 timestamp of the last resolved copy.
| export type ProjectType |
High-level type of a project — drives the special config view.
| export const STABLE_PROJECT_TYPES |
Project types that have actually been exercised end to end.
A type earns its place here by having its generated config accepted by the software it targets, not by round-tripping through a parser we also wrote. Phase 18 ran that matrix (.github/workflows/exporters.yml, and locally against containers) and every type below passed with a control case proving the validator rejects nonsense:
| type | evidence |
|---|---|
| wireguard | round-trip through parseWgConf |
| docker | Compose schema + .env pairing |
| nginx | round-trip through parseNginxConf |
| kubernetes | applied to a real k3s cluster; value decoded back out of it |
| ssh_config | parsed by OpenSSH ssh -G |
| traefik | loaded by Traefik v3; router and middleware report enabled |
| apache | httpd -t → Syntax OK |
| haproxy | haproxy -c → exit 0 |
| ansible | ansible-playbook --syntax-check → exit 0 |
| postgres | a real server authenticated using only the generated .pgpass |
Two of them only passed after a fix the validation itself found: six exporters never resolved ${ref} (invariant 5), and exportAnsible emitted a mapping followed by a sequence — not valid YAML in any parser.
The rule for adding one: nothing goes in this list on the strength of a fixture alone. A fixture proves we agree with ourselves.
| export const wireguard |
| export const docker |
| export const nginx |
| export const kubernetes |
| export const ssh_config |
| export const traefik |
| export const apache |
| export const haproxy |
| export const ansible |
| export const postgres |