Enterprise 版本
AST 审计追踪 — 深度参考
Enterprise AST 模块记录文档的变更,并为检索管线准备文档。
AstAuditTrailInterface在 Pro ASTMutationLog之上定义一个仅追加的、按文档的审计追踪。AstAuditEntry是对单次变更的不可变记录:节点标识、变更种类、页码、前/后快照、UTC 时间戳。InMemoryAstAuditTrail是该追踪契约的按进程参考实现。AstAwareChunker以深度优先遍历 AST,并为 RAG 摄取发出引用锚定的AstChunk值。
可用性与授权
标题为“可用性与授权”的章节此能力随 NextPDF Enterprise(nextpdf/enterprise)发行,并通过一份 Enterprise 层级授权信封激活。缺少该权益的部署不会加载此能力的类。比较各版本并获取授权。
AST 审计追踪表面由 enterprise.compliance.evidence 能力授权。一项被拒绝的权益会拒绝该功能。
| 层级 | 提供 |
|---|---|
| Core | AST 文档模型(AstDocument、AstNode、NodeId) |
| Pro | AST 变更流程与 MutationLog |
| Enterprise | 仅追加的按文档审计追踪;引用锚定的分块器 |
Enterprise 表面消费 Pro 变更日志。它不替换 AST 模型。
composer require nextpdf/enterprise:^3公共 API 表面
标题为“公共 API 表面”的章节| 符号 | 参数 | 默认行为 | 返回 | 抛出或失败于 | 说明 |
|---|---|---|---|---|---|
AstAuditTrailInterface::record() | string $documentSourceHash, MutationLog $log | 将日志中的每个变更条目转换为一个 AstAuditEntry 并追加 | void | 参考实现中无 | 以相同哈希重复调用会累积条目 |
AstAuditTrailInterface::findByDocument() | string $documentSourceHash | 按插入顺序返回为单个文档记录的条目 | list<AstAuditEntry> | 参考实现中无 | 无条目匹配该哈希时返回空列表 |
AstAuditTrailInterface::count() | 无 | 统计审计条目数 | int<0, max> | 参考实现中无 | 跨所有文档的总数,而非按文档 |
InMemoryAstAuditTrail | 无 | 作用域限定于当前进程的数组支持追踪 | 实现 AstAuditTrailInterface | 无 | 不持久;适用于单请求生命周期 |
AstAuditEntry | 构造函数提升所有字段 | 不可变审计记录 | 值对象 | 无 | final readonly;见下方签名代码块 |
AstAwareChunker::__construct() | int $maxChunkChars = 1500, int $overlapChars = 150 | 在构造时校验分块边界 | 实例 | 配置越界时抛出 InvalidArgumentException | 边界:16 <= maxChunkChars <= 1048576;0 <= overlapChars < maxChunkChars |
AstAwareChunker::chunk() | AstDocument $document | 深度优先遍历;标题分隔各块;叶子文本累积 | list<AstChunk> | 无 | 对于没有可累积文本的文档返回空列表 |
AstChunk | 构造函数提升所有字段 | 引用锚定的块记录 | 值对象 | 无 | final readonly;见下方签名代码块 |
namespace NextPDF\Enterprise\Ast;
use NextPDF\Pro\Ast\Mutation\MutationLog;
interface AstAuditTrailInterface{ public function record(string $documentSourceHash, MutationLog $log): void;
/** @return list<AstAuditEntry> */ public function findByDocument(string $documentSourceHash): array;
/** @return int<0, max> */ public function count(): int;}final readonly class AstAuditEntry{ public function __construct( public readonly string $documentSourceHash, public readonly string $nodeId, public readonly string $mutationType, public readonly int $pageIndex, public readonly array $before, public readonly array $after, public readonly DateTimeImmutable $occurredAt, ) {}}final class AstAwareChunker{ public function __construct( private readonly int $maxChunkChars = 1500, private readonly int $overlapChars = 150, ) {}
/** @return list<AstChunk> */ public function chunk(AstDocument $document): array {}}final readonly class AstChunk{ public function __construct( public readonly string $text, public readonly string $nodeId, public readonly int $pageIndex, public readonly ?array $bbox, public readonly string $nodeType, public readonly string $documentSourceHash, public readonly int $chunkIndex, ) {}}行为契约
标题为“行为契约”的章节审计追踪
标题为“审计追踪”的章节- 仅追加。 实现必须是仅追加的:一个已记录的条目不能通过此 API 被修改或移除。以相同哈希重复调用
record()会累积条目。 - 转换。
record()将 ProMutationLog的每个条目(通过MutationLog::all())转换为一个AstAuditEntry并追加。由单次record()调用产生的所有条目共享同一个 UTCoccurredAt时间戳。 - 按文档隔离。
findByDocument()按精确的文档源哈希过滤并保持插入顺序。count()是跨所有文档的总数。 - 快照。
before与after是以text_content为键的属性映射。一次updated变更填充两侧;inserted使before为空;deleted使after为空。mutationType是 ProMutationType枚举的字符串值:updated、inserted或deleted。 - 页码推导。
pageIndex从规范节点 ID(ast:{hash}:{page}:{seq})中提取。格式错误的节点 ID 会得到pageIndex0;该条目仍会被记录。
仅追加是所配置存储的一项契约,而非一项密码学属性。防篡改性与不可否认性来自该追踪如何被持久化与加盖时间戳(Evidence 模块),而非仅来自本模块。
分块器
标题为“分块器”的章节- 遍历。
chunk()从文档根开始以深度优先遍历 AST。 - 文本累积。 Paragraph、ListItem、TableCell、Code 或 Annotation 类型的叶子文本累积到当前缓冲区。容器类型(Document、Section、Artifact、FormField、Figure、Table、List、TableRow)被遍历但不发出文本。
- 分隔符。 Heading 节点会将当前缓冲区作为一个块刷出,并以该标题文本作为下一个缓冲区的起始。
- 拆分。 当累积文本将超出
maxChunkChars时,分块器填满剩余空间、刷出该块,并以最后overlapChars个字符加上溢出部分继续。长度计算基于 UTF-8 字符。 - 引用锚点。 每个
AstChunk携带其首个贡献节点的nodeId、pageIndex、bbox与nodeType,外加文档源哈希与一个从 0 开始的顺序chunkIndex。 - 收尾。 含非空白内容的尾部缓冲区会作为最后一个块刷出;仅含空白的剩余部分被丢弃,且块文本会被修剪。
边界情况与失败模式
标题为“边界情况与失败模式”的章节- 将同一个
MutationLog记录两次会累积重复条目;幂等性必须在上游强制执行。 - 一个全新的、未共享的
InMemoryAstAuditTrail始终为空。集成契约要求将一个共享的AstAuditTrailInterface实例同时交给产生变更的流程与读取审计的消费方,并在每次成功写入后调用record()。在此之前,findByDocument()返回空列表,count()返回 0。 - 内存追踪是按进程的且不持久;条目不会在创建它们的请求之外存活。生产环境需提供一个持久实现。
- 一个未能通过规范解析的节点 ID 不会中止记录;受影响的条目回退到
pageIndex0。 AstAwareChunker::__construct()以InvalidArgumentException拒绝退化的配置(overlapChars >= maxChunkChars,或maxChunkChars在[16, 1048576]之外)。这可防止分块期间缓冲区无限增长。- 当首个贡献节点不携带边界框时,
AstChunk::$bbox为null。 - 一个没有可累积文本的文档产生一个空的块列表。
- 本模块不执行任何密码学操作。用于防篡改的哈希、签署与加盖时间戳由 Evidence、Security 与 Signature 模块处理;FIPS 模式策略位于那里。
符合性
标题为“符合性”的章节| 行为 | 引用 |
|---|---|
| 增量更新 / 签名完整性背景 | ISO 32000-2:2020 §12.8 |
审计追踪是一项记录保存辅助手段。它支持审计式证据工作流;它不是一项认证,也不是一项法律证明,且 NextPDF 不持有任何认证。
开发说明
标题为“开发说明”的章节- 为跨请求保留提供一个持久的
AstAuditTrailInterface实现。在合规要求不可变性之处,将其持久化到一个具备 WORM 能力的存储中;仅追加保证的强度不超过其后端存储。 - 变更快照可能携带个人数据;数据驻留遵循运维方的存储。
- 该追踪按 Pro 变更日志的原样消费它;它不从文档状态重新推导变更。
- 分块器默认值(
maxChunkChars1500、overlapChars150)适合典型的 RAG 摄取;对于具有不同上下文预算的嵌入模型,可在文档所述边界内调优。 - 内部机制细节保留在源代码仓库的内部文档中,不在本手册范围内。
发布边界
标题为“发布边界”的章节本页仅记录外部可观察的行为与受支持的公共 API 表面。内部命名空间路径、辅助类、机制表、运行手册文件名以及工单前缀均不在范围内。