Skip to content

baseid-pctf

Implements all five PCTF components defined by DIACC, providing identity assurance evaluation, consent lifecycle management, hash-chained audit trails, policy validation, and bilingual (EN/FR) compliance reporting.

  • IAL Evaluation — 11 evidence types, 6 verification methods, Level 1/2/3 scoring with upgrade guidance
  • Consent Management — Creation, expiry, revocation, purpose limitation enforcement
  • Audit Trails — Hash-chained, tamper-detecting, append-only log with privacy redaction
  • Policy Engine — Multi-check validation (assurance, type, issuer, consent) with bilingual errors
  • Compliance Reports — Self-assessment covering all 5 PCTF components, EN/FR output
PCTF ComponentModuleKey Types
Verified PersonassuranceAssuranceLevelEvaluator, EvidenceType, EvidenceBundle
Credential ManagementpolicyPctfPolicy, PctfValidator, PolicyResult
Notice & ConsentconsentConsentManager, ConsentRecord, ConsentStatus
Digital IntegrityauditAuditLog, AuditEntry, RedactionPolicy
CompliancereportReportBuilder, PctfComplianceReport, ComponentStatus

Identity proofing evidence is evaluated against PCTF scoring rules:

use baseid_pctf::AssuranceLevelEvaluator;
use baseid_pctf::assurance::*;
let bundle = EvidenceBundle {
subject: "did:key:z6MkHolder".into(),
evidence: vec![
Evidence {
evidence_type: EvidenceType::InPerson,
verification: VerificationMethod::VisualInspection,
issuer: "did:web:servicecanada.gc.ca".into(),
timestamp: "2026-03-01T00:00:00Z".into(),
},
Evidence {
evidence_type: EvidenceType::Biometric,
verification: VerificationMethod::BiometricMatch,
issuer: "did:web:servicecanada.gc.ca".into(),
timestamp: "2026-03-01T00:00:00Z".into(),
},
Evidence {
evidence_type: EvidenceType::GovernmentPhotoId,
verification: VerificationMethod::DatabaseCheck,
issuer: "did:web:servicecanada.gc.ca".into(),
timestamp: "2026-03-01T00:00:00Z".into(),
},
],
};
let result = AssuranceLevelEvaluator::evaluate_bundle(&bundle);
// result.level == AssuranceLevel::High (Level 3)
// result.pctf_name == "Level 3"
// result.upgrade_possible == false
LevelPCTF NameRequirements
LowLevel 1Self-asserted identity or unverified evidence
SubstantialLevel 2Verified government document + additional factor
HighLevel 3In-person/supervised + biometric + government photo ID

GovernmentPhotoId, GovernmentDocument, Biometric, InPerson, SupervisedRemote, DocumentVerification, ChannelBinding, KnowledgeBased, SelfAsserted, AddressDocument, TrustedCredential

PCTFeIDASNIST 800-63TDIF
Level 1LowIAL1IP1
Level 2SubstantialIAL2IP2
Level 3HighIAL3IP3
use baseid_pctf::{ConsentManager, ConsentRecord};
let mut mgr = ConsentManager::new();
// Record consent
mgr.record_consent(ConsentRecord::new(
"consent-001",
"did:key:z6MkHolder", // subject
"did:key:z6MkVerifier", // recipient
vec!["givenName".into(), "dateOfBirth".into()],
"age-verification", // purpose
"2026-03-01T00:00:00Z", // timestamp
Some("2026-06-01T00:00:00Z".into()), // expires
));
// Check validity
let valid = mgr.find_valid_consents(
"did:key:z6MkVerifier", "age-verification", "2026-04-01T00:00:00Z"
);
// Revoke
mgr.revoke_consent("consent-001");
// Check expiry
mgr.check_all_expiry("2026-07-01T00:00:00Z");
FeatureMethodDescription
CreateConsentRecord::new()Active consent with purpose + data elements
Validateis_valid(now)Checks Active + not expired
Purpose checkcovers(elements, purpose)Verifies consent matches request
Revokerevoke()Transitions to Revoked status
Expirecheck_expiry(now)Auto-transitions to Expired
Queryfind_valid_consents()By recipient + purpose + time
use baseid_pctf::AuditLog;
use baseid_pctf::audit::{AuditAction, RedactionPolicy, RedactableField};
use serde_json::json;
let mut log = AuditLog::new();
log.append("e-1", "2026-03-01T10:00:00Z", AuditAction::CredentialIssued,
"did:web:gov.ca", json!({"type": "CanadianDigitalID"}));
log.append("e-2", "2026-03-01T11:00:00Z", AuditAction::ConsentGiven,
"did:key:z6MkHolder", json!({"verifier": "did:key:z6MkVerifier"}));
// Tamper detection
assert!(log.verify_chain());
// Query
let issued = log.by_action(AuditAction::CredentialIssued); // 1 entry
let march = log.by_time_range("2026-03-01T00:00:00Z", "2026-03-31T23:59:59Z");
// Export with PII redaction
let policy = RedactionPolicy {
redact: vec![RedactableField::Actor, RedactableField::Details],
replacement: "[REDACTED]".into(),
};
let jsonl = log.export(&policy); // JSON Lines format

CredentialIssued, CredentialPresented, CredentialVerified, CredentialRevoked, ConsentGiven, ConsentRevoked, DidCreated, DidResolved

use baseid_pctf::{PctfPolicy, PctfValidator};
use baseid_pctf::policy::PresentationContext;
use baseid_core::types::AssuranceLevel;
let policy = PctfPolicy {
min_assurance_level: AssuranceLevel::Substantial,
require_consent: true,
require_audit: true,
accepted_types: vec!["CanadianDigitalID".into()],
trusted_issuers: vec!["did:web:gov.ca".into()],
};
let result = PctfValidator::validate_presentation(&policy, &ctx, Some(&consent_mgr));
if !result.compliant {
for violation in result.violations() {
eprintln!("{}: {}", violation.name, violation.message);
// Bilingual: "Assurance level Level 1 below minimum Level 2 /
// Le niveau d'assurance Level 1 est inférieur au minimum Level 2"
}
}
CheckFieldDescription
assurance_levelmin_assurance_levelCredential IAL >= policy minimum
credential_typeaccepted_typesType in whitelist (empty = accept all)
trusted_issuertrusted_issuersIssuer in whitelist (empty = accept all)
consentrequire_consentValid consent exists for this presentation
auditrequire_auditInformational — flags audit requirement
use baseid_pctf::ReportBuilder;
use baseid_core::types::AssuranceLevel;
let report = ReportBuilder::new(
"BaseID Wallet",
AssuranceLevel::Substantial,
"2026-03-22T00:00:00Z",
)
.with_assurance_evaluation(true, 11)
.with_consent_management(true)
.with_audit_logging(true)
.with_crypto_integrity(true)
.with_revocation(true)
.build();
// report.overall_status == Conformant
// report.components.len() == 5
// report.title_fr == "Rapport d'auto-évaluation de conformité au CCNIP"
let json = serde_json::to_string_pretty(&report).unwrap();

BaseID validates protocol compliance through two mechanisms:

Tests OID4VCI 1.0, OID4VP 1.0, and HAIP 1.0 against the official OIDF test suite:

Terminal window
cd tools/conformance
bash setup.sh # Clone + build + TLS certs
podman-compose up -d # Start conformance suite
bash run-tests.sh all # Run OID4VCI + OID4VP + HAIP tests

See tools/conformance/README.md for details.

A complete mapping from every PCTF atomic process (BASE, SOUR, RESO, ESTAB, VALID, EVID, VERIF, MAINT) to BaseID code and tests is maintained in PCTF.md. Each criterion is tagged as:

  • IMPL — Implemented in BaseID code with tests
  • INFRA — BaseID provides infrastructure; Responsible Authority configures policy
  • PROC — Process/policy requirement fulfilled by the Responsible Authority

PCTF certification is achieved through the DIACC Voila Verified Trustmark Program:

  1. Self-assessmentReportBuilder generates bilingual compliance report
  2. Readiness advisor — Engage a DIACC-accredited advisor
  3. Level 1 assessmentDTLab documentation review
  4. Level 2 assessment — DTLab technical examination
  5. Trustmark issuance — DIACC issues Voila Verified trustmark