Secret Attributes
The attribute value type Secret stores credentials — passwords, client secrets, API keys, bot tokens, private keys, refresh tokens — encrypted at rest. The engine enforces it: a Secret value is encrypted on every write, no public API returns it, and readers only see whether a value is set.
The Secret value type is available from System CK model 2.5.0 and the engine release that ships it. Models that use it must depend on System >= 2.5 (see System dependency).
When to Use Secret
Use Secret for every attribute whose value grants access to something: passwords, client secrets, API keys, tokens, private keys and passphrases, connection strings that contain credentials. Values that identify an account without granting access — user names, client ids, tenant ids — stay String.
A Secret value is used server-side only:
- the communication controller decrypts secrets when it builds adapter configuration,
- pipelines read a secret on demand with the
RevealSecret@1node, - GraphQL, MCP and octo-cli only report whether a value is set (see Secret Attributes in the API).
Defining a Secret Attribute
$schema: https://schemas.meshmakers.cloud/construction-kit-elements.schema.json
attributes:
- id: Password
valueType: Secret
description: Password of the mailbox account
Assign it to a type like any other attribute:
types:
- typeId: EMailReceiverConfiguration
derivedFromCkTypeId: System/Configuration
attributes:
- id: ${this}/UserName
name: UserName
- id: ${this}/Password
name: Password
isOptional: true
The value type sits on the attribute definition. If a definition is shared by credential and non-credential attributes, split it first and convert only the credential attribute.
Rules
The compiler enforces the following rules for a Secret attribute. The numbers refer to the compiler messages below.
| Rule | Message |
|---|---|
No defaultValues — a credential never ships with the model | 70 |
No autoCompleteValues and no autoIncrementReference | 71 |
| Not an attribute of an association role | 71 |
Effective ownership is always Secret. An unset ownership becomes Secret; any other declared ownership is an error | 72 |
| Not indexable — the stored value is ciphertext | 73 |
Not referenced by display rules (displayNameRule, displayDescriptionRule) | 74 |
| Not referenced by owner attribute paths | 69 |
The model depends on System >= 2.5 | 75 |
A record that contains a Secret sub-attribute declares a valid recordKey | 76, 77 |
In addition, Secret attributes are never part of query columns, formulas, runtime queries, archive column paths or CrateDB columns.
Ownership Secret means: a blueprint re-apply keeps the stored value, and runtime exports (ExportRt, deep-graph export) never contain it.
Secrets in Records
A Secret attribute may be a sub-attribute of a record. Because a record array is always written as a whole, the engine must decide per element whether an empty secret means "unchanged". It matches incoming and stored elements by a record key, which the record definition names with recordKey:
$schema: https://schemas.meshmakers.cloud/construction-kit-elements.schema.json
records:
- recordId: ValueOverride
recordKey: Path # names a sub-attribute of the record
attributes:
- id: ${this}/Path
name: Path
- id: ${this}/Value
name: Value # String: non-secret overrides stay readable
- id: ${this}/SecretValue
name: SecretValue # attribute definition with valueType: Secret
- id: ${this}/IsSecret
name: IsSecret
This is the shape of the Helm ValueOverride record in System.Communication 3.41: a secret override sets IsSecret and carries its value in SecretValue; legacy entries that keep an enc:v1 value in Value still deploy but are deprecated.
Rules for recordKey:
- A record whose own or inherited attributes contain a Secret attribute must have an effective
recordKey(own, or inherited from the nearest base record). This applies to the record type, regardless of whether it is used asRecordorRecordArray, because another model can reuse it in an array (message 76). - The key names a sub-attribute of the record that is required, not Secret and of value type
String,Int,Int64orEnum(message 77). - Single
Recordattributes carry over by position (there is exactly one element); the key is used forRecordArrayattributes.
How the carry-over works in the API is described in Secrets in records.
System Dependency
A model that uses Secret attributes must depend on System >= 2.5, so that an engine that does not know the value type fails with a clear dependency error instead of misreading the attribute:
# ckModel.yaml
dependencies:
- System-[2.5,3.0)
Versioning
| Change | Classification |
|---|---|
valueType changed from String to Secret | MINOR |
valueType changed from Secret to anything else, or any other valueType change | MAJOR |
Record recordKey set, cleared or changed | MINOR |
String → Secret is Minor because stored values stay readable: readers accept legacy plaintext in a Secret slot until the encryption sweep has run (see Secret Encryption Key Ring). The effective ownership becomes Secret. Clients that select the value as a string must switch to the is-set state before the model change is rolled out. See also Versioning Rules.
Blueprint Seeds
Blueprint seed data may contain only empty values for Secret attributes; secrets are set after installation. See Secret attributes in seed data.
Compiler Messages
| No. | Key | Level | Message |
|---|---|---|---|
| 70 | SecretAttributeHasDefaultValues | ERROR | Secret attribute '{ckAttributeId}' declares defaultValues. A Secret attribute cannot have default values - a credential must never ship with the model; set it after installation. |
| 71 | SecretAttributeAssignmentInvalid | ERROR | Secret attribute '{attributeName}' ('{ckAttributeId}') of '{ckElementId}' is invalid: {reason} |
| 72 | SecretAttributeOwnershipNotSecret | ERROR | Secret attribute '{attributeName}' of '{ckElementId}' declares ownership '{ownership}'. The effective ownership of a Secret attribute is always 'Secret'; remove the override or declare 'ownership: Secret'. |
| 73 | SecretAttributeIndexed | ERROR | Index of type '{ckTypeId}' references Secret attribute path '{attributePath}'. Secret attributes cannot be indexed - the stored value is ciphertext. |
| 74 | SecretAttributeReferencedByDisplayRule | ERROR | Display rule '{ruleProperty}' of type '{ckTypeId}' references Secret attribute path '{attributePath}'. Display rules cannot reveal Secret attributes. |
| 75 | SecretAttributeRequiresSystemDependency | ERROR | Construction kit model '{modelId}' uses Secret attributes and must depend on System >= {minimumVersion} (declared: {declaredDependency}). Declare the dependency as 'System-[{minimumVersion},3.0)' so engines that do not know the Secret value type fail with a dependency error. |
| 76 | RecordWithSecretRequiresRecordKey | ERROR | Record '{ckRecordId}' contains Secret attribute(s) {secretAttributes} but declares no 'recordKey'. A record with Secret sub-attributes must name the sub-attribute that identifies an element, so a secret left empty on a record array replace can be carried over from the stored element with the same key. |
| 77 | RecordKeyInvalid | ERROR | Record key '{recordKey}' of record '{ckRecordId}' is invalid: {reason} |
Reasons reported with message 71:
- Secret attributes cannot be attributes of an association role
- autoCompleteValues are not allowed - they would publish candidate secrets with the model
- autoIncrementReference is not allowed - a generated sequence number is not a secret
Reasons reported with message 77:
- the record has no attribute with this name
- a Secret attribute cannot be the record key
- the key attribute must be of value type String, Int, Int64 or Enum
- the key attribute must not be optional - an element without a key cannot be matched
An owner attribute path that points at a Secret attribute is reported with the existing message 69 (OwnerAttributeInvalid).
See Also
- Secret Attributes in the API — GraphQL semantics
- RevealSecret@1 — reading a secret in a pipeline
- Secret Encryption Key Ring — keys, rotation, migration, monitoring