SEC Rule 17a-4 WORM 合規¶
SEC Rule 17a-4(f) 要求受監管的金融機構(券商、投資顧問、交易所)以不可改寫、不可刪除(WORM)的方式保留電子通訊記錄與業務文件,保存期限依文件類型從 2 年至 6 年不等。
法規要求對應¶
| Rule 17a-4(f) 要求 | 技術含義 | NextPDF Enterprise 實現 |
|---|---|---|
| 不可改寫(Non-rewriteable) | 寫入後無法修改任何位元 | WORM 封存鎖定,SHA-512 完整性封印 |
| 不可刪除(Non-erasable) | 保留期內無法刪除 | 保留期政策強制執行,刪除請求拒絕並記錄 |
| 序列化存取控制 | 防止未授權存取 | mTLS + 租戶隔離存取控制 |
| 即時索引(Real-time index) | 支援 SEC 審查人員快速存取 | 結構化索引、全文檢索 API |
| 指定第三方下載能力 | SEC 可直接提取記錄 | SecAuditorAccessGrant API |
| 書面說明(Written undertaking) | 機構需提交合規聲明 | 合規報告產生器 |
核心 API¶
WormArchive¶
use NextPDF\Enterprise\Compliance\Sec\WormArchive;
use NextPDF\Enterprise\Compliance\Sec\RetentionPolicy;
use NextPDF\Enterprise\Compliance\Sec\ArchiveRecord;
$retentionPolicy = RetentionPolicy::create(
documentType: 'broker-dealer-communication',
retentionYears: 3,
retentionMonths: 0,
allowEarlyDeletion: false,
legalHoldCapable: true,
);
$archive = new WormArchive(
storageAdapter: $s3WormAdapter, // S3 Object Lock 或同等 WORM 儲存
retentionPolicy: $retentionPolicy,
integrityAlgorithm: 'SHA-512',
);
$record = $archive->store(
document: $pdfBytes,
metadata: ArchiveRecord::create(
documentId: $docId,
documentType: 'trade-confirmation',
entityId: 'BD-12345',
createdAt: new DateTimeImmutable(),
retentionUntil: new DateTimeImmutable('+3 years'),
)
);
// $record->archiveId() — 不可變封存 ID
// $record->integrityHash() — SHA-512 完整性雜湊
// $record->retentionExpiry() — 保留到期日
PHP Compatibility
This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.
RetentionPolicy¶
use NextPDF\Enterprise\Compliance\Sec\RetentionPolicy;
use NextPDF\Enterprise\Compliance\Sec\DocumentType;
// 預設保留期(依 Rule 17a-4 規定)
$policy = RetentionPolicy::forDocumentType(DocumentType::TradeConfirmation); // 3 年
$policy = RetentionPolicy::forDocumentType(DocumentType::CustomerComplaint); // 4 年
$policy = RetentionPolicy::forDocumentType(DocumentType::FinancialStatement); // 6 年
$policy = RetentionPolicy::forDocumentType(DocumentType::BrokerDealerAgreement); // 6 年
$policy = RetentionPolicy::forDocumentType(DocumentType::ElectronicCommunication); // 3 年(2022 修正)
SecIndexBuilder¶
Rule 17a-4(f)(3)(iii) 要求維護可供 SEC 審查的索引:
use NextPDF\Enterprise\Compliance\Sec\SecIndexBuilder;
use NextPDF\Enterprise\Compliance\Sec\IndexQuery;
$indexBuilder = new SecIndexBuilder($archive);
// 產生符合 SEC 要求的索引報告
$index = $indexBuilder->buildIndex(
dateRange: new DateRange(
from: new DateTimeImmutable('2024-01-01'),
to: new DateTimeImmutable('2024-12-31'),
),
documentTypes: [DocumentType::TradeConfirmation, DocumentType::CustomerComplaint],
format: IndexFormat::Csv, // SEC 偏好 CSV 格式
);
// 授予 SEC 審查人員存取
$accessGrant = $indexBuilder->grantAuditorAccess(
auditorId: 'SEC-EXAM-2025-001',
expiresAt: new DateTimeImmutable('+30 days'),
scope: AccessScope::ReadOnly,
);
完整性驗證¶
WORM 封存後,任何時刻均可驗證文件未被竄改:
use NextPDF\Enterprise\Compliance\Sec\IntegrityVerifier;
$verifier = new IntegrityVerifier($archive);
$result = $verifier->verify(archiveId: $record->archiveId());
if (!$result->isIntact()) {
// 觸發 SEC 強制要求的事件通報程序
$incidentReporter->reportIntegrityBreach(
archiveId: $record->archiveId(),
detectedAt: new DateTimeImmutable(),
expectedHash: $result->expectedHash(),
actualHash: $result->actualHash(),
);
}
封存文件生命週期¶
flowchart LR
A[文件建立] --> B[WORM 封存]
B --> C{法律留存?}
C -->|是| D[延長保留]
D --> E{留存解除?}
E -->|是| C
E -->|否| F[繼續保留]
C -->|否| G{保留期到期?}
G -->|否| H[定期完整性驗證]
H --> G
G -->|是| I[SEC 通知確認]
I --> J[安全銷毀]
J --> K[銷毀稽核記錄] 案例:交易確認書封存¶
use NextPDF\Enterprise\Compliance\Sec\SecComplianceBundle;
$bundle = SecComplianceBundle::create(
storageAdapter: $s3WormAdapter,
indexAdapter: $elasticsearchAdapter,
);
// 批次封存每日交易確認書
foreach ($dailyConfirmations as $confirmation) {
$pdf = $pdfFactory->createTradeConfirmation($confirmation);
$bundle->archiveAndIndex(
document: $pdf,
type: DocumentType::TradeConfirmation,
entityId: $confirmation->brokerId(),
referenceId: $confirmation->tradeId(),
);
}
// 產生月度合規報告
$report = $bundle->generateComplianceReport(
period: ReportingPeriod::lastMonth(),
includeIntegrityAudit: true,
);