| Internet-Draft | ApertoMemory | July 2026 |
| Ferro | Expires 23 January 2027 | [Page] |
AI assistants and agents accumulate long-term memory about their users. This memory is typically stored in proprietary, provider-held silos: it cannot be moved between tools, its integrity cannot be verified, and its confidentiality depends entirely on the provider. This document specifies the ApertoMemory format: a canonical, signed, client-side-encrypted representation of AI memory objects, together with a portable single-file export container. Memory objects are encoded in deterministic CBOR, signed with COSE_Sign1, and encrypted with COSE_Encrypt0 under keys derived from and controlled by the user. A storage or synchronisation server handling ApertoMemory objects has zero access to their content, authorship, or semantic timestamps.¶
This revision specifies format_version 2, which cryptographically binds every signature to the author it claims and to the cleartext envelope around it, and derives trust from which key verified an object rather than from a declared field. format_version 1, described by earlier revisions of this document, carries a known forgeable- provenance defect and MUST NOT be implemented for new deployments.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 23 January 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Modern AI tools build user-specific memory: preferences, facts, learned behaviours, and procedural knowledge that improve the quality of assistance over time. This memory constitutes some of the most sensitive personal data in existence, and it is currently locked inside each provider's infrastructure. Switching tools destroys accumulated context, creating a form of vendor lock-in that operates on personal data rather than on price or features.¶
Existing portability efforts move memory as cleartext JSON with no integrity protection, no verifiable provenance, and no confidentiality guarantees against the storage layer. This document takes the opposite starting point: memory is encrypted and signed on the user's device before it goes anywhere, and every party except the user's own runtime is treated as untrusted.¶
This document specifies (1) the memory object data model and its deterministic CBOR encoding, (2) the cryptographic envelope (sign-then-encrypt with COSE) and the two bindings that authenticate it, (3) trust derivation and Custody Records, (4) the conversion paths between trust levels (migration, import, and the AI boundary), (5) the user-controlled key hierarchy including per-scope access separation, and (6) the portable export container. Synchronisation protocols and memory extraction from conversations are out of scope.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
format_version 1, specified by draft-ferro-apertomemory-00 and -01, contained three related defects, disclosed as [GHSA]: nothing bound a signature to the author_key_id it claimed, so a signer could sign with its own key while claiming another identity and verification still succeeded; nothing authenticated the cleartext envelope (id, scope_id, format_version), so a storage server could rewrite those fields undetected; and verification failed open, returning content together with an ignorable boolean. An object crafted this way, once surfaced to an AI system as a trusted memory, could carry instructions attributed to the user (Section 15.2).¶
format_version 2 closes all three with the two bindings of Section 5 and the fail-closed derivation rules of Section 6. Implementations MUST NOT create format_version 1 objects, and MUST NOT report them as verified (Section 12). Implementations of the earlier revisions of this document do not conform to this one.¶
The schema and rules of this document bind Producers and Consumers differently, and both obligations are required for conformance.¶
A Producer is bound strictly: it MUST NOT emit an object that violates this specification (Section 3.2). A Consumer has a second, separate obligation: it MUST handle input that does not match this specification without failing catastrophically. Hostile and corrupt objects exist, and refusing to read a whole container because one object inside it is malformed is a denial of service on the user's entire memory. So a validator SHOULD reject a payload carrying an empty Custody Record, because no Producer may write one -- and an implementation MUST still read the container it lives in, degrade that object's trust, and carry on. Both are required; neither substitutes for the other. Where the two obligations meet, this document states which is which.¶
Conformance for format_version 2 is defined by the test-vector set of Appendix A: fourteen vectors, six of which are refusal cases. Reproducing the byte strings of the positive vectors is necessary but not sufficient; an implementation that reproduces every byte and refuses none of the attacks implements the defect the vectors exist to catch. This is stated with unusual emphasis because format_version 1 was byte-compatible with implementations that checked nothing.¶
A sealed Memory Object is a CBOR map containing exactly the fields a Blind Server is permitted to see, plus an encrypted envelope. All semantic content, including authorship and semantic timestamps, lives inside the envelope.¶
The normative schema is expressed in CDDL [RFC8610]:¶
sealed-object = {
1 => bstr .size 16, ; id: 128-bit random (NOT UUIDv7:
; time-ordered ids leak creation time)
2 => bstr .size 16, ; scope_id: opaque random identifier
3 => uint, ; format_version (this document: 2;
; 1 = legacy, see Section on Legacy)
4 => bstr, ; COSE_Encrypt0 (AES-256-GCM, COSE alg 3,
; MTI; alg 24 OPTIONAL) whose plaintext
; is a COSE_Sign1 (EdDSA) over
; memory-payload. Both carry
; envelope-aad as external_aad.
? 5 => bstr .size 16, ; dek_wrap_ref (RESERVED)
}
memory-payload = {
1 => mem-type,
2 => tstr, ; content: UTF-8 text (this rev: text only)
3 => confidence, ; 0.0 .. 1.0
4 => provenance,
5 => trust-level, ; INFORMATIONAL ONLY - Section on Trust
? 6 => [* tstr], ; tags
7 => timestamps, ; SEMANTIC times - MUST NOT appear
; in cleartext
? 8 => embedding, ; RESERVED - MUST travel encrypted only
? 9 => epoch-seconds, ; expires_at. RESERVED
? 10 => {* tstr => any}, ; extensions. RESERVED
? 20 => custody, ; present iff re-sealed - Section on
; Custody Records
* uint => any, ; unrecognised keys MUST be preserved
; on rewrite
}
mem-type = &( episodic: 1, semantic: 2, procedural: 3 )
confidence = float .ge 0.0
provenance = {
1 => tstr, ; producing tool (e.g. "amem-cli/0.2")
2 => bstr .size 8, ; author_key_id: first 8 bytes of
; SHA-256 of the author's Ed25519
; public key. BOUND to the verifying
; key - Section on Author Binding.
? 3 => tstr, ; session identifier
}
trust-level = &( self: 1, trusted: 2,
third-party: 3, unverified: 4 )
; third-party (3) is reserved: this revision derives only
; self, trusted and unverified. Retained for wire
; compatibility with v1 payloads.
timestamps = { 1 => epoch-seconds, ? 2 => epoch-seconds }
; created, updated
epoch-seconds = uint ; seconds since 1970-01-01T00:00:00Z,
; as a BARE uint (see below)
embedding = { 1 => tstr, 2 => [* float] } ; model, vector
¶
Object identifiers MUST be generated from a cryptographically secure random source. Time-ordered identifiers (such as UUIDv7) MUST NOT be used, as they leak creation-time metadata to the Blind Server.¶
The normative range of confidence is 0.0 to 1.0 inclusive. CDDL tooling does not express a closed float interval portably -- chained control operators on float ranges are rejected by common validators -- so the upper bound is stated here and enforced by test vector 013 rather than by the schema. A Producer MUST NOT write a value outside this range. A Consumer that reads one MUST NOT propagate it: the object is authentic, so it is not refused, but the value is reported as absent and the schema violation flagged (Section 8.3).¶
Timestamps are bare unsigned integers, deliberately not the CDDL prelude "time" (a tag-1 epoch datetime). Every object written so far, and every test vector, carries an untagged integer; requiring the tag now would invalidate every existing vault to gain nothing. The schema records what the format is, not what it might have been. (This divergence was found by validating the vectors with a second, independent CDDL implementation.)¶
Unrecognised integer keys in memory-payload MUST be preserved byte for byte when an object is re-encoded (see Section 13).¶
Keys 8 (embedding), 9 (expires_at) and 10 (extensions) of memory-payload, and key 5 (dek_wrap_ref) of sealed-object, are reserved: they carry the shapes given above, but no current implementation interprets them. They are read, preserved verbatim on rewrite, and otherwise ignored. Consumers MUST NOT rely on them.¶
expires_at in particular is NOT enforced: an expired object is still returned. No expiry guarantee exists until an implementation states that it honours the field.¶
This subsection exists because a schema that describes a field nobody implements is the same defect as documentation that claims a defence the code does not provide. Stating the gap is the fix.¶
A conformant Producer MUST fail rather than emit an object where: confidence is absent, NaN, infinite, or outside 0.0 to 1.0; content is not a non-empty UTF-8 string; or mem-type is outside the enumeration. It MUST NOT write an empty or incomplete Custody Record (Section 7).¶
A Consumer, by contrast, is deliberately more tolerant on read: it reports an unrecognised mem-type verbatim rather than refusing the object, because refusing to read is a worse failure than reporting an unknown type. Strict on write, lenient on read.¶
All structures are serialised as deterministically encoded CBOR as defined in Section 4.2 of [RFC8949].¶
The envelope construction is sign-then-encrypt:¶
Placing the signature inside the encryption prevents the Blind Server from learning or correlating authorship. The server can neither learn nor verify authorship; signature verification is performed by Consumers after decryption, and Consumers MUST reject objects whose signature does not verify (Section 6).¶
The mandatory-to-implement AEAD algorithm is AES-256-GCM (COSE algorithm 3, [RFC9053]). ChaCha20/Poly1305 (COSE algorithm 24) is OPTIONAL. Each DEK MUST encrypt exactly one object; nonce reuse under a given key is thereby structurally excluded, and the random nonce serves as defence in depth.¶
All algorithms are referenced by COSE algorithm identifiers. Future migration (including to post-quantum algorithms) is a registry change, not a format change.¶
format_version 1 objects carried no cryptographic relationship between a signature, the author it claimed, and the cleartext envelope around it. format_version 2 binds both.¶
The following structure, serialised as deterministic CBOR, is supplied as COSE external_aad to BOTH the COSE_Sign1 and the COSE_Encrypt0 of every object:¶
envelope-aad = [ uint, ; format_version, as in the envelope bstr .size 16, ; id, as in the envelope bstr .size 16, ; scope_id, as in the envelope ]¶
It is never transmitted: the reader reconstructs it from the cleartext envelope. Rewriting id, scope_id or format_version therefore invalidates the AEAD tag (test vector 005). A version downgrade -- rewriting format_version from 2 to 1 to strip the bindings -- is detected for the same reason (test vector 006).¶
The trust-level field of memory-payload is carried for wire compatibility and MUST NOT be read as authoritative. A Consumer derives trust from which key verified the signature:¶
| Signature verified by | Derived trust |
|---|---|
| the vault Owner's key | self |
| an accepted third-party key (Keyring) | trusted |
| no key, or a key no longer accepted | unverified |
Trust is evaluated at read time against the current Keyring, and MUST NOT be frozen into the object: revoking a key downgrades every memory attributed to it, with no rewrite.¶
Verification is fail-closed. A Consumer that cannot authenticate an object MUST NOT return its content by default; reading it requires an explicit opt-in and yields trust "unverified".¶
Consumers MUST treat content whose derived trust is not "self" as untrusted DATA and MUST NOT give it instruction-level privilege (Section 15.2). This is the whole point of the author binding: without it, hostile text could claim to be the user's own memory.¶
An object carrying a Custody Record additionally reports its authorship as described in Section 7: derived provenance distinguishes the signer of the object as it stands from the author of its content, and reports "signed", "attested" or "unknown" authorship accordingly.¶
Re-sealing an object changes its signer. A re-sealed object's signature therefore proves CUSTODY, not authorship -- and the object says so, by carrying a Custody Record (memory-payload key 20):¶
custody = {
1 => uint, ; format_version it was re-sealed from
2 => bstr .size 8, ; author_key_id claimed by the
; original object
3 => epoch-seconds, ; when it was re-sealed
? 4 => bstr .size 8, ; author_key_id PROVEN at re-seal
; time; absent = authorship could
; not be proven
}
¶
The rules, each pinned by a test vector:¶
| custody | field 4 (proven author) | trust | authorship | author_key_id |
|---|---|---|---|---|
| absent | -- | self / trusted | signed | the verified signer |
| present | names an accepted key | trusted | attested | the proven author |
| present | absent or unaccepted | unverified | unknown | none reported |
Note on test vector 014: its payload deliberately does NOT conform to the custody rule above -- an empty map has none of the required keys. That is the point of the vector, and the keys stay mandatory on purpose: making them optional would declare an empty Custody Record legal to WRITE, which it is not. A validator will reject that payload, and it should; an implementation must nevertheless read it, degrade it to "unverified", and continue (Section 2).¶
Most of this format holds trust constant: a sealed object is written at one trust level and read back at the same one. Three paths do not. They take data from one trust domain and emit it into another: migration (from the unbound format_version 1 into format_version 2), import (from an external container into a vault), and the AI boundary (from sealed objects into an AI system's context window). Every defect found in this format so far was found on one of these paths: the forgeable provenance of format_version 1 ([GHSA]), the import that destroyed the identity of an existing vault, the migration that would have re-signed hostile objects as the Owner's own (caught in review before release), and the custody attestation honoured from any accepted key. This is not a coincidence. A forgery only pays off where trust changes, so these are the paths an attacker studies, and they are specified here with the same care as the cryptography.¶
The rule uniting the three subsections: a conversion path MUST NOT output data at a higher trust level than it can prove for its input, and where proof is impossible the path MUST either refuse or explicitly mark the output as unproven. Silent upgrade is the defect class; each subsection names the form it takes on that path.¶
Migration re-seals format_version 1 objects as format_version 2. Because re-sealing changes the signer, migration is a transfer of trust, not a format conversion: after migration, the object's signature proves custody by whoever re-sealed it, not authorship. An object may therefore keep trust "self" only if its original signature actually verifies under the Owner's currently accepted signing key.¶
A migration tool MUST classify every object into exactly one of the following outcomes, and MUST NOT invent a fourth:¶
The defect this taxonomy exists to prevent is provenance laundering: a migration that re-signs unproven objects under the Owner's key without a Custody Record would let any hostile v1 object sitting in a scope come out of an ordinary upgrade signed by the user and trusted as their own -- converting a store-compromise into persistent prompt injection with first-person authority (Section 15.2). An earlier, unreleased revision of the reference implementation had exactly this defect.¶
Two further requirements:¶
Import converts sealed objects from an external container (Section 10) into vault state. The container arrives over an untrusted channel, so import is the path by which an attacker delivers crafted objects wholesale; exploitation of [GHSA] required exactly this (or write access to the victim's store).¶
An importer MUST enforce all of the following, in an order such that nothing is written until every check has passed:¶
Import moves ciphertext; it MUST NOT assign or upgrade trust. Objects acquired by import are opened later under the ordinary derivation rules (Section 6) against the Keyring in force at read time. In particular, an imported Custody Record is honoured only if the verified signer is the vault Owner (test vector 011): a container is not a side channel for attestations.¶
Finally, the checks above MUST live in the single import implementation used by every entry point -- library, command line, and any adapter. In an earlier release the guard existed only in the MCP adapter, and the library path underneath it had none. A guard on one door of a building with several doors is a claim the building cannot keep.¶
The last conversion is the one the format exists for: sealed objects become cleartext in an AI system's context window, typically through a local adapter such as an MCP server. This crossing leaves the cryptographic domain entirely -- no signature, binding, or AEAD tag survives into the context window -- so everything the Consumer will ever know about an object's trust must be derived before the boundary and travel across it as explicit labels.¶
At this boundary:¶
The three paths differ in mechanism but not in shape: each converts data across a trust boundary, each has hosted a real defect, and each is specified as a set of refusals. An implementation that reproduces every byte of the test vectors but refuses nothing implements the defect these paths exist to close.¶
All keys derive from, or are wrapped towards, material under exclusive user control:¶
passphrase --Argon2id--> master secret (32 bytes)
master secret --HKDF-SHA256--> Ed25519 seed (signing)
master secret --HKDF-SHA256--> X25519 seed (key agreement)
scope KEK (32 bytes random)
<-- ECDH-ES(X25519) + HKDF-SHA256 + AES-256-KW -- master
object DEK (32 bytes random, single object)
<-- AES-256-KW -- scope KEK
¶
The Argon2id [RFC9106] parameters are fixed: memory 64 MiB, iterations 3, parallelism 4, 16-byte random salt, 32-byte output (the second recommended parameter choice of RFC 9106).¶
Key derivation uses HKDF-SHA256 [RFC5869]; key agreement uses X25519 [RFC7748]. HKDF info strings provide domain separation: "apertomemory/v1/sign", "apertomemory/v1/ka", and "apertomemory/v1/kek-wrap" concatenated with the scope_id. Binding the KEK wrap to the scope_id ensures a wrapped KEK cannot be transplanted between scopes.¶
The key hierarchy did not change in format_version 2, and the HKDF info strings deliberately retain the "v1" label: altering them would break every existing vault for no security benefit. The label names the hierarchy, not the object format.¶
Key wrapping uses AES Key Wrap [RFC3394]. Server-side key escrow is out of scope of this format: a lost passphrase without a recovery mechanism means unrecoverable memory, and implementations SHOULD offer user-held recovery codes.¶
Each Scope has its own KEK. A tool authorised for a subset of scopes receives only those KEKs and is cryptographically unable to open objects outside them. The scope_id visible to the Blind Server is an opaque random identifier carrying no semantic information about the scope's name or purpose.¶
The export container serialises a complete memory set into a single file (conventionally with the .amem extension):¶
amem-export = {
1 => uint, ; export_version (this document: 1)
2 => vault-public, ; salt, public keys, wrapped scope
; KEKs, accepted author keys
3 => [* bstr], ; sealed-objects (encoded)
4 => {* bstr => bstr}, ; object id => wrapped DEK
}
vault-public = {
"salt" => bstr .size 16,
"sign_pub" => bstr .size 32,
"ka_pub" => bstr .size 32,
"scopes" => {* tstr => scope-entry },
? "known_keys" => {* tstr => bstr .size 32 },
; accepted third-party author keys:
; hex key_id => Ed25519 public key
}
scope-entry = {
"scope_id" => bstr .size 16,
"kek_wrapped" => bstr,
"eph_pub" => bstr .size 32,
}
¶
The container holds only public keys, wrapped keys, and sealed objects; it is therefore safe to transport over untrusted channels. Possession of the file plus the user's passphrase is sufficient to reconstruct the entire memory on a new device.¶
Two rules govern reading a container:¶
Interoperability requires more than parseability. A Consumer claiming full conformance MUST take the type, confidence, creation time, and scope of memory objects into account when selecting which objects to surface to an AI system, and SHOULD prefer higher confidence and more recent objects when context is limited -- subject to the validation rule of Section 8.3 on out-of-range confidence.¶
Consumers MUST apply the derivation rules of Section 6 and the boundary rules of Section 8.3 whenever memory content is surfaced to an AI system.¶
format_version 1 objects carry neither binding: their signature proves only internal consistency, and their envelope is unauthenticated. They MUST NOT be reported as verified. They MAY be read under the same explicit opt-in as any unauthenticated object, always as trust "unverified" (test vector 009), and SHOULD be re-sealed by migration.¶
Re-sealing follows Section 8.1: only objects whose authorship can be proven under a key the reader accepts may be re-sealed without a Custody Record.¶
The format_version field governs breaking changes, and is protected against downgrade by the envelope binding (Section 5.1). Additive changes use new integer keys in memory-payload or the reserved extensions map; implementations MUST preserve unrecognised keys byte for byte when re-encoding, so that older tools do not destroy data written by newer tools.¶
This section is to be removed before publishing as an RFC.¶
This section records the status of known implementations of the format defined by this specification, per the process in [RFC7942]. Listing here does not imply endorsement.¶
This format protects memory at rest and in transit against: a compromised or curious storage/synchronisation server; the storage provider itself; and network observers. With format_version 2 this includes servers that tamper: rewriting an object's envelope or downgrading its version is detected (Section 5.1). It intentionally does not protect against the AI runtime to which the user grants memory access (which must read cleartext to function), nor against malware on the user's own device. Specifications and products building on this format MUST NOT claim protections beyond this model.¶
A memory object is text that will eventually be placed into an AI system's context. An attacker who can introduce objects into a user's memory achieves persistent prompt injection: instructions that resurface in every future conversation. This is substantially more dangerous than single-conversation injection.¶
The format's defence is the chain from author binding to derived trust to the boundary rules: Consumers MUST verify signatures before use, MUST NOT elevate non-"self" objects to instruction privilege, and SHOULD surface provenance to users when importing third-party memory sets. format_version 1 made this defence claimable but not keepable, because authorship was forgeable (Section 1.2); format_version 2 exists to make it hold.¶
A Blind Server still observes object counts, sizes, and synchronisation timing, from which usage patterns can be inferred. Semantic timestamps and embeddings MUST only exist inside the encrypted envelope. Implementations SHOULD pad sealed objects to size classes. Residual inference from traffic analysis is acknowledged and not fully mitigated by this format.¶
Embedding vectors permit approximate reconstruction of the text they were computed from. They are therefore content, not metadata, and MUST be encrypted like content. Server-side semantic indexing of embeddings is incompatible with this format's security goals; search is a client-side operation over decrypted objects.¶
The AEAD construction of this format uses a 96-bit random nonce, but its security does not rest on random nonce uniqueness: each DEK is generated for exactly one object and performs exactly one encryption operation. Nonce reuse under a given key, the catastrophic failure mode of AES-GCM, is therefore structurally excluded rather than probabilistically avoided; the random nonce is defence in depth.¶
Implementations MUST NOT reuse a DEK for a second encryption operation, including re-encryption of a modified object: a modified object is a new object with a new DEK. Because every key encrypts a single message, the per-key invocation limits of AES-GCM are not a practical concern for conforming implementations. Key wrapping (AES-KW, RFC 3394) is a deterministic, nonce-free construction and is used only over uniformly random key material, which is the setting it is designed for.¶
The key hierarchy is designed so that rotation cost is proportional to the scope of the compromise being addressed:¶
Because trust is derived at read time (Section 6), removing a key from the Keyring immediately downgrades every object attributed to it, including objects attested by Custody Records, with no rewrite. A future revision will define an interoperable representation for superseded-key metadata; until then it is implementation-defined.¶
Deployments that wrap key material towards per-device keys can revoke a device by removing that device's wraps and rotating the scope KEKs used for objects created thereafter. Remaining devices keep access to historical objects without mass re-encryption.¶
Revocation of this kind is forward-looking: a revoked device that has already cached KEKs or plaintext can retain what it held at revocation time. This is a fundamental property of any end-to-end-encrypted system, not a defect of this format, and specifications building on this format MUST NOT claim otherwise. Where retroactive lockout of stored ciphertext is required, implementations achieve it by re-wrapping the affected DEKs under new KEKs and destroying the old wraps (cryptographic erasure of the old access path).¶
An .amem container carries the vault salt and the public signing key, which together give an attacker holding the file an offline verification oracle against the passphrase: derive, compare, repeat. The Argon2id parameters (memory 64 MiB, iterations 3, parallelism 4) are the only barrier, and they bound the attacker's rate, not their eventual success against a weak passphrase. Users MUST be advised to choose strong passphrases; implementations MUST NOT weaken the fixed Argon2id parameters.¶
Erasure of an individual object is achieved by destroying its wrapped DEK (cryptographic erasure); the sealed blob becomes permanently unreadable even if retained by append-only storage. This provides a technical mechanism for erasure obligations such as those in data protection regulation.¶
The export container is itself a data portability mechanism: it gives users a complete, machine-readable, provider-independent copy of their AI memory, aligned with portability rights such as Article 20 of the GDPR.¶
This document requests registration of the following media type in the "Media Types" registry, per [RFC6838]:¶
The normative conformance artefact for format_version 2 is the machine-readable vector set [VECTORS], generated by the reference implementation. An implementation is conformant if it reproduces the byte strings of the positive vectors AND refuses every case marked as a refusal. Six of the fourteen vectors are refusal cases (marked * below).¶
| Vector | Exercises |
|---|---|
| 001 key-hierarchy | Argon2id, HKDF, Ed25519 and X25519 derivation; author_key_id computation. |
| 002 kek-wrap | ECDH-ES(X25519) + HKDF + AES-KW scope-key wrapping. |
| 003 sealed-object-v2 | Full format_version 2 object with envelope-aad on both COSE layers. |
| 004 forged-authorship * | Signed with one key while declaring another's author_key_id; MUST be refused under every key (Section 5.2). |
| 005 rewritten-envelope * | id and scope_id rewritten by a storage server; decryption MUST fail (Section 5.1). |
| 006 version-downgrade * | format_version forced from 2 to 1 to strip the bindings; MUST be detected. |
| 007 custody-attested | Migrated third-party memory; opens as trust "trusted", never "self"; proven author reported (Section 7). |
| 008 custody-unproven | Quarantined object; opens as "unverified" with no author; unproven claim exposed separately. |
| 009 legacy-v1 * | format_version 1 object; MUST NOT be reported as verified; opt-in read as "unverified" (Section 12). |
| 010 inconsistent-kid * | Protected-header kid contradicts payload author_key_id; self-inconsistent object MUST be refused. |
| 011 custody-from-non-owner * | Custody record signed by an accepted third party; MUST NOT be honoured; opens as "unverified" with no author. |
| 012 custody-naming-unaccepted-key | Attestation names a key outside the Keyring; authorship "unknown", no author reported. |
| 013 out-of-range-confidence | Authentic object with confidence 42.0; opens, but the value is reported as absent and flagged (Section 8.3). |
| 014 empty-custody-map | Empty custody sub-map; degrades to "unverified" without raising; container reading continues (Section 2). |
Test vectors 001 and 002 of the previous revisions remain valid for the key hierarchy, which is unchanged; their inlined values appear in draft-ferro-apertomemory-01.¶
The memory-type taxonomy (episodic, semantic, procedural) follows established cognitive-science terminology also adopted by other AI memory efforts.¶
The author thanks Valentina Tognizioli, not only for what she did, but for who she is. Watching how she used and shaped AI agents in her everyday work sparked the idea for this format. But her real contribution is harder to cite: a way of seeing things differently, of noticing what matters, of never giving up. It changed how the author approaches his own work. Every page of this document carries a trace of her. Without her, none of this would exist.¶