| 开发者 | dantianhealth |
|---|---|
| 更新时间 | 2026年11月10日 14:46 |
| PHP版本: | 8.2 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
[dpma_hub] or [dpma_kb]. Restricted documents never appear in search or listings for people outside their audience.
dpma_faq_allowed_iframe_hosts allowlist.)
Pro add-on (separate plugin)
For audit-bound and growing organisations, Dantian Policy Management Pro adds:
dantian-policy-management folder to /wp-content/plugins/.[dpma_hub] to a page — your staff visit that page, see the policies they have to read, and acknowledge them. The Compliance Overview dashboard updates shortly after, and shows when its figures were last refreshed.The core loop — controlled publication, version-by-version acknowledgements, role-based access, owner approval workflow, and auditor-ready exports — is what most teams pay thousands of dollars a year for in dedicated SaaS tools. The Free plugin covers that loop entirely, self-hosted, on infrastructure you already own. Areas where enterprise SaaS tools go further: multi-stage approval routing, AI-driven workflow automation, a choice of PDF template designs, and integrations with HR or security-audit systems — most of which are available in the optional Pro add-on.
Yes — and everything below is in the free plugin, with no add-on required. Underneath the governance features is a complete knowledge base:
[dpma_docs] turns any tagged set of documents into a docs site with category landing pages, a sidebar article tree, previous/next navigation, and clean deep-linkable URLs.Either, per item. Mark a document or FAQ as Public and anyone can read it; to let signed-out visitors use the plugin's search boxes too, enable Settings → Access & Privacy → Public REST API Access (off by default). Leave it Internal and it is limited to the roles you choose. Restricted content is filtered out of search results and listings — not just hidden behind a link — so one site can run a public help centre and a staff-only policy library side by side.
The plugin provides the technical foundations those frameworks typically require — controlled publication, role-based access, acknowledgement evidence, document integrity records, and full audit history — but meeting a specific regulatory standard is always the organisation's responsibility and depends on your policy content, processes, and the rest of your environment. Because the plugin is self-hosted and never transmits data externally on its own, it fits cleanly into regulated environments where cloud tools are not permitted. Several frameworks explicitly require self-hosting or controlled data residency; this plugin is built to those constraints by default.
No. The Free plugin makes no external network requests during normal operation. The one exception is a check to this site's own uploads address that the private upload folder is not publicly readable. The Free plugin alone is fully self-contained.
Every acknowledgement record stores: the staff member's user account and role, the document and version they acknowledged, a digital fingerprint of the document text at that version (a SHA-256 hash), the timestamp, and how it was recorded (by the reader, by an administrator on their behalf, or by an owner sign-off). Each record is sealed when it is written with a tamper-evident integrity seal — a keyed checksum (HMAC-SHA256) made with your site's secret keys, so someone who can edit the database but cannot read wp-config.php cannot forge it — and the attestation export states, for every record, whether it still matches its seal. Changing the site's secret keys (AUTH_KEY / AUTH_SALT in wp-config.php) makes existing seals read as modified until they are re-sealed. You can also optionally capture how long they spent reading and how much of the content they actually read — switch it on under Settings → Acknowledgements & Notifications and both values are recorded on the acknowledgement and included in the attestation export.
Export the attestation report at any time and you have a checksummed record ready to hand to an auditor. If the policy text is later updated, the fingerprint in the old acknowledgement records still matches the original version — the evidence trail does not silently rewrite itself.
The Free plugin includes a built-in file importer: upload a ZIP of Word (.docx), PDF, plain-text, or Markdown files and the plugin creates a draft document from each one. After import you configure audience, visibility, and review cycles inside the plugin. Most teams migrate from an existing policy-management system by exporting their library to PDF/Word and importing via this tool.
Free runs the complete policy acknowledgement loop on its own:
Yes — the plugin ships a dedicated Policy Auditor user role with read-only access to acknowledgement logs, attestation exports, and the compliance dashboard, but no ability to create or modify documents. Assign the role to your external auditor's WordPress user during the audit window; revoke after.
Yes. The Edit Suggestions feature (enabled in Settings → Features) lets the roles you select for each document type submit suggested changes to a document. The original stays unchanged; the suggestion goes to a moderation queue where editors or admins can approve, edit-and-approve, or reject. Each accepted suggestion creates a new version; when version approval is on and the document has an owner, that version waits for the owner's approval before it goes live.
WordPress 6.7 or later and PHP 8.2 or later, with the PHP mbstring extension — standard on virtually all hosts. If mbstring is missing, the plugin shows an admin notice and stays inactive until your host enables it. PDF export also uses PHP's DOM and iconv extensions, and PDF text import uses iconv and zlib — all enabled in standard PHP builds.
Activate it per site. Each site then keeps its own document library, acknowledgement records, and roles. Network activation is not supported: the plugin's database tables are created for the site being activated, not for every site on the network, so subsites would run against tables that do not exist. There is also no "share policies across the network" feature. If you need either, drop a question in the support forum.
Many user-facing strings are editable. Per document, you set the acknowledgement intro text and the confirmation checkbox text. In Settings you can edit the access-denied screen text, every email subject, and the body of manually sent (individual) reminders. The acknowledge button label and the body of the scheduled reminder emails are fixed text (translatable). For full template control, use the standard WordPress filter pattern — see the user and developer documentation.
No. The plugin registers its own dpma_document and dpma_faq post types and does not take over post types from a theme or another plugin, so content in those types stays where it is. Their keys can be renamed under Dantian Policy Management → Settings → System Configuration → Post Types & Taxonomies, but not to a key another plugin or theme already uses.
Each document has a configurable expiry period (in days). When a user acknowledges, their record is valid for that window. After expiry the user is prompted to re-acknowledge. A new version resets the requirement when its change type is at or above the Re-Acknowledgement Trigger Level (default: major versions only; Settings → Acknowledgements & Notifications). Expired and expiring-soon records appear on the Compliance Overview dashboard.
Deleting a user account does not anonymise or delete their acknowledgement records. The records keep the deleted account's user ID, IP address and the rest of the record, so your audit trail survives. When the account is deleted, the plugin keeps a one-way hash of their email address (made with a key unique to your site; the address itself is not stored) with the former user ID, so the Tools → Export Personal Data and Tools → Erase Personal Data tools still find their records when you enter that email address later. If a new account now uses the same address, one request covers both: the new account's records and the deleted account's. Completing an erasure request removes that hash. The key that makes the hash is generated by the plugin and kept in its own (non-autoloaded) option, so changing your site's secret keys (AUTH_SALT / AUTH_KEY) does not affect it. To manage the key yourself, define DPMA_PRIVACY_HASH_KEY in wp-config.php (a long random string, set once): changing or removing it later stops hashes made with it matching, in the same way. An erasure request anonymises acknowledgement records rather than deleting them — the user ID, the IP address and any reason given for acting on someone's behalf are removed, but the record itself (document, version, timestamp, the role the person held, how it was given, any quiz answers and score, reading time and reach, and the expiry date) stays intact — and the behaviour is documented under Settings → Privacy → Policy Guide. The plugin always anonymises acknowledgement records on erasure; there is no setting or filter to delete them or to keep the user ID instead.
[dpma_hub] Displays the Document Hub: the visitor's outstanding acknowledgements, search, document-type tabs, and recent / popular / recently viewed lists. Attributes:
show_obligations - Show the visitor's outstanding-acknowledgement summary (default: true)show_search - Show the search bar (default: true)show_tabs - Show document-type tabs (default: true)show_recent / show_popular / show_recently_viewed - Show those side lists (default: true; Recently Viewed needs Track View User Identity on)recent_count / popular_count - Items in those lists (default: 5)initial_show - Documents per category box before a "View all N documents" link to the category archive (default: 5; 0 = heading and link only). Boxes for documents with no category list everything, with a "Show N more" button after this manydoc_types - Order of the type tabs, comma-separated (default: policies,procedures,guides,forms)tag - Limit the hub's search to documents with this tag; tabs and lists are not filtered
[dpma_search]placeholder - Search input placeholder texttag - Limit results to documents with this tag (comma-separate several to require all of them)
[dpma_documents]type - Filter by document type slugcategory - Filter by category slugtag - Filter by document tag slug (comma-separate several to match any of them)limit - Number of documents to show (default: 20; at most 500 unless a site raises or lifts that with the dpma_document_list_max filter)columns - Grid columns (default: 1, max: 3; a larger value is treated as 3)
[dpma_kb]type - Restrict to a specific document type slugcategory - Show only this single category slug (default: all categories)show_filter - Display a category filter nav at the top: 'true' or 'false' (default: 'false')initial_show - Documents per category section before its "View all N documents" link (default: 10; 0 = heading and link only)
Examples:
[dpma_kb] - All categories with their documents
[dpma_kb show_filter="true"] - All categories with a clickable category nav at the top[dpma_kb type="policy" show_filter="true"] - Only Policy documents, grouped by category[dpma_kb category="hr"] - HR category only
[dpma_faqs]category - Filter by FAQ category slug (e.g., 'technical', 'policy-questions')limit - Maximum number of FAQs to display (default: 200)style - Display style: 'accordion' (default), 'list', or 'grid'show_search - Show search box: 'true' or 'false' (default: 'false')search_only - Hide the FAQs until the visitor searches (default: 'false')orderby - Sort by: 'title' (default), 'date', 'views', or 'order' (a sort-order value set in the FAQ's Source Document panel)order - Sort direction: 'ASC' or 'DESC' (default: 'ASC')heading_level - Heading level for each question in the list and grid styles (default: 3)
Examples:
[dpma_faqs] - Show all FAQs in accordion style
[dpma_faqs category="technical" show_search="true"] - Show technical FAQs with search[dpma_faqs style="grid" limit="6" orderby="views"] - Show 6 most viewed FAQs in grid layout
[dpma_faq]id - FAQ post ID (required)heading_level - Heading level for the question (default: 2)
Example:
[dpma_faq id="123"] - Display FAQ with ID 123
[dpma_docs]
[dpma_hub].)
Documents join a portal by carrying its tag, provided their document type is switched on for portals (Show in Docs Portal ([dpma_docs]) under Settings → Content Management → Manage Document Types; by default just Guide, plus documents with no type). Order within a portal is set by the document's Portal order field; equal values sort alphabetically by title.
Attributes:
tag (required) — Document tag slug that scopes the portal.facet — Comma-separated tag slugs shown as a section bar across the top (e.g. facet="free,pro"); the chosen section carries through every document link.show_search — Show a tag-scoped search box on the landing page: 'true' or 'false' (default: 'true')title — Optional heading above the portal (default: none)
Examples:
[dpma_docs tag="user-guide"] — Portal for all documents tagged "user-guide"
[dpma_docs tag="onboarding" title="Onboarding Guide"] — Portal with custom heading[dpma_docs tag="api-reference" show_search="false"] — Portal without search
Note: A document should carry only one portal tag. If a document has multiple portal tags, it joins the first matching portal alphabetically.show_acknowledged / show_pending - Show the acknowledged and the pending lists (default: true)user_id - Show another user's acknowledgements instead; only for someone allowed to edit that user (default: the signed-in user)heading_level - Heading level for the title shown when viewing another user (default: 2)
[dpma_pending_approvals]heading_level - Heading level for the section headings (default: 2)
[dpma_compliance_report]dpma_compliance_report_capability filter changes who), and to documents the viewer may open.
Attributes:
document_id - Document post ID (required)roles - Comma-separated role slugs to limit the report to (default: the document's whole audience)limit - Maximum number of people to list (default: 200)
[dpma_user_acknowledgements]role / role__in - Limit the picker to one role, or to several (comma-separated)show_acknowledged / show_pending - Show the acknowledged and the pending lists (default: true)orderby / order - Sort the picker by a user field such as 'display_name' (default) and 'ASC' (default) or 'DESC'heading_level - Heading level for the user's name (default: 3; 2 to 6)
[dpma_bookmarks]dpma_saved_items_login_prompt filter can turn that into empty output).
Attributes:
tag - Show only bookmarks carrying this tag (comma-separate several to require all of them)
[dpma_saved_searches]target - The id of the search box that Apply fills in (default: dpma-search-input)The plugin provides REST API endpoints under the dpma/v1 namespace:
GET /dpma/v1/search?q=query - Search documents (requires the q parameter)GET /dpma/v1/documents - List documentsGET /dpma/v1/faqs - List FAQsGET /dpma/v1/my-outstanding-acknowledgements - The signed-in user's documents still awaiting their acknowledgement (signed-in users only)wp/v2), which apply the same visibility rules.
By default these endpoints require a logged-in user, so document, search, and FAQ content is never exposed to anonymous visitors. If you run a public knowledge base and want anyone to read documents without signing in, enable Settings → Access & Privacy → Public REST API Access (off by default). Per-document visibility and confidentiality restrictions still apply when it is on, and anonymous requests are rate limited to deter abuse.
The plugin keeps background export files such as attestation PDFs (kept for one day, then deleted), temporary import sandboxes, and the original of each imported PDF whose text could not be read in a private folder beside your web folder, named dantian-policy-management-private- plus a short code. Nothing there has a web address, on any server, and files leave it only through the plugin's permission checks. The PDF render and font cache stays in wp-content/uploads/dantian-policy-management/; its files have unguessable names and the folder carries an Apache .htaccess deny rule.
If no folder outside the web root can be used, the private files stay in that uploads folder too, but only while this server is measured refusing direct requests for it (checked daily). If it is not, exports and imports do not start, nothing personal is written, and Tools → Site Health gives two fixes. Name a folder outside the web root in wp-config.php:
define( 'DPMA_PRIVATE_DIR', '/a/folder/outside/the/web/root' );
Or, because nginx does not read .htaccess, add this server-block rule (Tools → Site Health also recommends it for the PDF cache if the folder can be opened by its web address):
location ^~ /wp-content/uploads/dantian-policy-management/ { deny all; return 403; }
The ^~ prefix makes it win over any regex location (such as a static-file caching rule).
On a host with several web servers, a folder beside the web folder may exist on only one of them, so a task can fail or a download can come back "not found"; nothing is exposed, and setting DPMA_PRIVATE_DIR to shared storage fixes it. If you set DPMA_PRIVATE_DIR to a new folder, imported originals move there by themselves within a day and stay downloadable meanwhile, then the old private folder is removed; a task running at that moment may fail and can be started again. If you move a site to a new folder on the same server, its old private folder is left behind for you to delete, because it could belong to another live site.
[dpma_hub] tabbed hub, [dpma_search], [dpma_documents] filterable listing, [dpma_kb] knowledge-base layout and FAQs ([dpma_faqs] / [dpma_faq]) with helpful/unhelpful feedback, bookmarks and saved searches. Search logging is off until an administrator turns it on.[dpma_docs] reading format for guides and help articles: category navigation, content and an auto-generated table of contents, clean URLs and an optional facet section bar.[dpma_my_acknowledgements], [dpma_compliance_report], [dpma_pending_approvals], [dpma_compliance_progress].dpma_-prefixed content types (dpma_document, dpma_faq) and taxonomies, a REST API, filters and actions, and the Dpma\Clock, Dpma\Content_Gate and Dpma\Privacy_Registry classes for extensions. Requires the PHP mbstring extension.