Submodules¶
PDV Vault¶
pdv_vault holds the Master KEK in OpenBao or
HashiCorp Vault instead of in a local Key: it wraps each per-user Subject KEK
with the store's Transit engine, so the root key never reaches Drupal.
Enable with drush en pdv_vault and follow
Master KEK in OpenBao or Vault for the full setup
(preparing the store, the settings.php connection, creating the Transit Key,
and selecting it as the Master KEK).
PDV Webform¶
pdv_webform provides a Vault file Webform element (pdv_file):
when filling a form, the user can either upload a new file or reuse a
document from their own vault. Consuming code reads the chosen bytes
uniformly through PdvFileValue, regardless of which source the user
picked.
- The vault picker lists only the current user's document items (records are structured data, not files, so they are excluded here).
- Add the element to a form. Its
#kindrestricts it to one or more item kinds: a single machine name (id_card), or several comma-separated, each optionally labeled (id_card:ID card, passport:Passport). When more than one kind is offered for save, the user picks which kind an uploaded file is stored as. - With
#offer_vault_savethe element also offers to save an uploaded file back to the user's vault for reuse, gated on write access just like the record handler below. - On the submission page the value renders as a download link. The vault branch is decrypted on the fly through a dedicated endpoint gated by the submission's view access; if the underlying document was later deleted, the link is gone and the download returns "not found" rather than erroring.
The element reads the chosen bytes through the shared
VaultClientInterface, so consuming code is the same whether the vault is
in-process or reached over a vault connection.
Mapping elements to a record (the PDV record-map handler)¶
pdv_webform also adds a PDV: map vault records Webform handler.
The mapping lives on the elements as two custom properties (set via
the element's Custom properties / Source, so they exist only where
you add them - nothing is forced onto other elements):
#pdv_record_field=kind.field(e.g.civil_status.full_name) binds an element to a record field.#pdv_record_store=kindon a checkbox is the per-kind "store in my vault" consent.
The handler has a Vault connection setting (which vault identity the form acts as: a local consumer on a same-site vault, or a configured connection on a remote consumer site). Attach it to a form, then for each authenticated user:
- Prefill: elements bound with
#pdv_record_fieldare pre-filled from the user's record of that kind, when they have one. - Save: on submit, each ticked store-consent checkbox saves the mapped fields into the user's record of that kind (creating or updating it), provided the configured consumer has write access. If it does not, the submit is blocked with a single one-click link to grant write access - the user keeps everything they entered, grants in a new tab, then resubmits - rather than the save failing silently afterwards.
Multiple kinds per form are supported, each with its own consent checkbox.
Turning vault features off¶
Vault features on webforms can be switched off two ways. Either makes every form behave as a plain webform: no prefill, no "use my vault data" prompt, no save-to-vault, and the Vault file element collapses to a plain upload.
- Per user: each user can tick Don't use my personal data vault on webforms on their own account-edit page. This is the everyday choice and works on every site, including a remote consumer site that has no vault tab.
- Site-wide (operators): Configuration -> Personal Data Vault -> PDV
Webform (
/admin/config/pdv/webform, needsadminister webform) has a temporary stand-down that turns the integration off for all users at once, for an incident or maintenance (e.g. the vault is unreachable or a key is being rotated). To switch the feature off for good, remove the form's handler and Vault file elements instead.
Enable with drush en pdv_webform (requires
Webform).
PDV Test Console¶
pdv_test_console is a development-only consumer simulator, gated by
the use pdv test console permission, at
/admin/config/pdv/test-console. It lets you act as a consumer to:
- Request access to one or more kinds from a user; the form generates a callback URL + state token so the post-decision redirect round-trips through the test console.
- Read a document or record (allowed with a grant or read-trust; denied otherwise, which demonstrates the authorization check).
- Store request (auto-stored when write-trusted, otherwise parked for the owner to review on their vault page).
It is meant for trying out the sharing flows by hand and should not be enabled on production.
Enable with drush en pdv_test_console.
PDV Mail¶
pdv_mail sends the default email for pdv notifications - currently the
dormant-vault deletion warnings (and a final notice when a
vault is erased), to the owner's account email. pdv core stays out of the mail
business: it only dispatches pdv.dormancy events, and this submodule turns
them into messages through Drupal's mail manager, using whatever mail system
the site has configured.
It de-duplicates per owner, so an owner with several vaults expiring together gets one message, not one per vault; the reminders still escalate across the configured lead-times.
Enable it for out-of-the-box warning emails, or leave it disabled and deliver
them your own way: no-code with PDV ECA, or by subscribing to the
pdv.dormancy events yourself (for example through the Message stack). Enable
with drush en pdv_mail.
The body is built as plain text with blank-line paragraph breaks and no markup of its own. A plain-text mail system sends it as-is; an HTML-first one (such as Symfony Mailer) runs it through a text format, so the blank lines become paragraphs and the links become clickable, with no template to maintain here.
PDV ECA¶
pdv_eca surfaces pdv's domain events to
ECA (Event - Condition - Action), so an
operator can react to vault activity - send a notification, write a log, call a
webhook, create a Message - without
writing code. It is the no-code counterpart to PDV Mail's fixed
default email; pdv core stays event-only, and you choose how events are
delivered.
It adds one ECA event, PDV: vault event, that covers every pdv.* channel
and action. In the model you narrow it down with two optional filters:
- Channel - e.g.
pdv.dormancy,pdv.item,pdv.grant. Leave blank to match all channels. - Action - e.g.
warned,erased,stored. Leave blank to match all actions.
The event provides these tokens for conditions and downstream actions:
| Token | Description |
|---|---|
[event:channel] |
The event channel, e.g. pdv.dormancy. |
[event:action] |
The event action, e.g. warned. |
[event:resource] |
The audited resource id, e.g. pdv:vault/default/1. |
[event:owner_uid] |
The vault owner's user id, or 0 if none. |
[event:owner_mail] |
The vault owner's email address. |
[event:owner_langcode] |
The owner's preferred language code. |
[event:tenant] |
The tenant id, or empty for the default tenant. |
[event:deadline] |
Dormancy deadline as a Unix timestamp, or 0. |
[event:deadline_formatted] |
The same deadline as a human-readable date. |
For example, to react when a dormant vault is warned: filter on channel
pdv.dormancy, action warned, then add whatever action fits - a Send email
to [event:owner_mail], a webhook, a log entry. The tokens above carry the
details (deadline, tenant, owner).
A worked example: email through Easy Email¶
To send the dormant-vault warning as a no-code, editable email, pair pdv_eca
with Easy Email. In the model,
react to PDV: vault event (channel pdv.dormancy, action warned) and add
Easy Email's Send Easy Email action with the template recipient set to
[event:owner_mail].
On a multilingual site, precede the send with a Set language action set to
[event:owner_langcode], so the template renders in the owner's preferred
language rather than the current (request or site) language; it must run before
the send. A single-language site does not need this step.
pdv stays event-only; the wording lives in an editable Easy Email template.
Enable with drush en pdv_eca (requires
ECA).
Localized notifications. ECA's Send email renders its inline subject and body from the model configuration in the source language, so it is not the way to email an owner in their own language. For owner-language delivery use PDV Mail (fixed templates) or PDV Message (editable, translatable templates); both render in the recipient's preferred language.
PDV Message¶
pdv_message delivers the dormant-vault warnings and erasures from
operator-editable, translatable Message templates instead of fixed,
code-defined text. It builds a Message
from a template, renders it in the owner's preferred language, and emails it.
Like PDV Mail it is a delivery choice for the same pdv.dormancy events -
enable one or the other, not both.
It ships two templates, editable at Structure -> Message templates and translatable on their Translate tab:
pdv_dormancy_warned- the warning, with@deadline,@login_urland@vault_urlplaceholders the module fills in (the deadline is formatted in the owner's language).pdv_dormancy_erased- the final "deleted" notice.
Partial 0 of each template is the subject, partial 1 the body. French translations ship with the module; add other languages on the Translate tab.
Enable with drush en pdv_message (requires
Message).
Cross-site modules¶
These let a consumer site read and write a vault on a separate Drupal site. See Client-server configuration for the setup and the API reference for the wire contract.
- PDV Client API (
pdv_client_api) - the sharedVaultClientInterfacecontract. A site binds it to either the in-processLocalVaultClient(same-site, provided bypdv) or the HTTPRemoteVaultClient(cross-site, provided bypdv_client), so consumer code is identical either way. - PDV Server API (
pdv_server_api) - install on the vault. Exposes the vault'sConsumerApiover HTTP (OAuth2 bearer auth) plus the consent ceremony landing. Never exposes the raw crypto. - PDV Client (
pdv_client) - install on the consumer (a site with no vault of its own). Provides the OAuth client-credentials token provider, the remoteConsumerApiover HTTP, the consent round-trip, and a per-user handle store. Requires the Key module: the OAuth client secret is held in a Key, not in configuration. - PDV Server Audit Trail Bridge (
pdv_audit_trail) - optional bridge on the vault that records every pdv transition (grants, trust, items, reads, writes, consent) into Audit Trail for a tamper-evident chain. This is the vault's own authoritative audit. Enable withdrush en pdv_audit_trail(requires Audit Trail). - PDV Client Audit Trail (
pdv_client_audit_trail) - optional bridge that records each remote vault call the client makes into Audit Trail, complementary to the vault's own authoritative audit. An unconfigured audit backend is logged, not fatal - it never breaks a vault call.