Merge branch 'platform-dev' of git.cloudarix.de:ahmido/TenantAtlas into platform-dev

This commit is contained in:
Ahmed Darrazi 2026-05-02 12:04:06 +02:00
commit 10b542fa98
14 changed files with 1064 additions and 18 deletions

View File

@ -199,13 +199,16 @@ private function executeReviewDerivedGeneration(
$options = $reviewPack->options ?? [];
$includePii = (bool) ($options['include_pii'] ?? true);
$includeOperations = (bool) ($options['include_operations'] ?? true);
$generatedAt = now();
$fileMap = $this->buildReviewDerivedFileMap(
reviewPack: $reviewPack,
review: $review,
tenant: $tenant,
snapshot: $snapshot,
includePii: $includePii,
includeOperations: $includeOperations,
generatedAt: $generatedAt,
);
$tempFile = tempnam(sys_get_temp_dir(), 'review-pack-');
@ -219,7 +222,7 @@ private function executeReviewDerivedGeneration(
'review-packs/%s/review-%d-%s.zip',
$tenant->external_id,
(int) $review->getKey(),
now()->format('Y-m-d-His'),
$generatedAt->format('Y-m-d-His'),
);
Storage::disk('exports')->put($filePath, file_get_contents($tempFile));
@ -241,6 +244,7 @@ private function executeReviewDerivedGeneration(
'operation_count' => $includeOperations ? (int) ($reviewSummary['operation_count'] ?? 0) : 0,
'highlights' => is_array($reviewSummary['highlights'] ?? null) ? $reviewSummary['highlights'] : [],
'publish_blockers' => is_array($reviewSummary['publish_blockers'] ?? null) ? $reviewSummary['publish_blockers'] : [],
'delivery_bundle' => $this->deliveryBundleSummary($review),
'evidence_resolution' => [
'outcome' => 'resolved',
'snapshot_id' => (int) $snapshot->getKey(),
@ -258,8 +262,8 @@ private function executeReviewDerivedGeneration(
'file_size' => $fileSize,
'file_path' => $filePath,
'file_disk' => 'exports',
'generated_at' => now(),
'expires_at' => now()->addDays($retentionDays),
'generated_at' => $generatedAt,
'expires_at' => $generatedAt->copy()->addDays($retentionDays),
'summary' => $summary,
]);
@ -582,13 +586,21 @@ private function assembleZip(string $tempFile, array $fileMap): void
* @return array<string, string>
*/
private function buildReviewDerivedFileMap(
ReviewPack $reviewPack,
TenantReview $review,
Tenant $tenant,
EvidenceSnapshot $snapshot,
bool $includePii,
bool $includeOperations,
\Carbon\CarbonInterface $generatedAt,
): array {
$reviewSummary = is_array($review->summary) ? $review->summary : [];
$deliveryMetadata = $this->deliveryBundleMetadata(
reviewPack: $reviewPack,
review: $review,
snapshot: $snapshot,
generatedAt: $generatedAt,
);
$sections = $review->sections
->filter(fn (mixed $section): bool => $includeOperations || $section->section_key !== 'operations_health')
@ -599,7 +611,8 @@ private function buildReviewDerivedFileMap(
'version' => '1.0',
'tenant_id' => $tenant->external_id,
'tenant_name' => $includePii ? $tenant->name : '[REDACTED]',
'generated_at' => now()->toIso8601String(),
'generated_at' => $generatedAt->toIso8601String(),
'delivery_bundle' => $deliveryMetadata,
'tenant_review' => [
'id' => (int) $review->getKey(),
'status' => (string) $review->status,
@ -622,11 +635,17 @@ private function buildReviewDerivedFileMap(
'note' => RedactionIntegrity::protectedValueNote(),
],
], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR),
'summary.json' => json_encode($this->redactReportPayload(array_merge([
'tenant_review_id' => (int) $review->getKey(),
'review_status' => (string) $review->status,
'review_completeness_state' => (string) $review->completeness_state,
], $reviewSummary), $includePii), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR),
'summary.json' => json_encode($this->redactReportPayload(array_merge(
[
'tenant_review_id' => (int) $review->getKey(),
'review_status' => (string) $review->status,
'review_completeness_state' => (string) $review->completeness_state,
],
$reviewSummary,
[
'delivery_bundle' => $this->deliveryBundleSummary($review),
],
), $includePii), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR),
'sections.json' => json_encode($sections->map(function ($section) use ($includePii): array {
$summaryPayload = is_array($section->summary_payload) ? $section->summary_payload : [];
$renderPayload = is_array($section->render_payload) ? $section->render_payload : [];
@ -641,6 +660,14 @@ private function buildReviewDerivedFileMap(
'render_payload' => $this->redactReportPayload($renderPayload, $includePii),
];
})->all(), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR),
ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME => $this->buildExecutiveEntrypoint(
review: $review,
tenant: $tenant,
snapshot: $snapshot,
reviewSummary: $reviewSummary,
includePii: $includePii,
generatedAt: $generatedAt,
),
];
foreach ($sections as $section) {
@ -659,6 +686,195 @@ private function buildReviewDerivedFileMap(
return $files;
}
/**
* @return array<string, mixed>
*/
private function deliveryBundleSummary(TenantReview $review): array
{
return [
'contract' => ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT,
'executive_entrypoint_file' => ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME,
'appendix_files' => ['metadata.json', 'summary.json', 'sections.json'],
'interpretation_version' => $review->controlInterpretationVersion(),
];
}
/**
* @return array<string, mixed>
*/
private function deliveryBundleMetadata(
ReviewPack $reviewPack,
TenantReview $review,
EvidenceSnapshot $snapshot,
\Carbon\CarbonInterface $generatedAt,
): array {
return [
'contract' => ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT,
'artifact_family' => 'review_pack',
'review_pack_id' => (int) $reviewPack->getKey(),
'generated_at' => $generatedAt->toIso8601String(),
'released_review' => [
'id' => (int) $review->getKey(),
'status' => (string) $review->status,
'completeness_state' => (string) $review->completeness_state,
'published_at' => $review->published_at?->toIso8601String(),
],
'interpretation_version' => $review->controlInterpretationVersion(),
'evidence_basis' => [
'snapshot_id' => (int) $snapshot->getKey(),
'snapshot_fingerprint' => (string) $snapshot->fingerprint,
'completeness_state' => (string) $snapshot->completeness_state,
'generated_at' => $snapshot->generated_at?->toIso8601String(),
],
'entrypoint' => [
'file' => ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME,
'role' => 'executive_entrypoint',
'audience' => 'executive',
'format' => 'text/markdown',
],
'appendix' => [
[
'file' => 'metadata.json',
'role' => 'bundle_metadata',
'description' => 'Structured delivery metadata and artifact role map.',
],
[
'file' => 'summary.json',
'role' => 'review_summary_appendix',
'description' => 'Structured released-review summary truth.',
],
[
'file' => 'sections.json',
'role' => 'section_detail_appendix',
'description' => 'Structured released-review section detail.',
],
],
];
}
/**
* @param array<string, mixed> $reviewSummary
*/
private function buildExecutiveEntrypoint(
TenantReview $review,
Tenant $tenant,
EvidenceSnapshot $snapshot,
array $reviewSummary,
bool $includePii,
\Carbon\CarbonInterface $generatedAt,
): string {
$package = is_array($reviewSummary['governance_package'] ?? null)
? $this->redactReportPayload($reviewSummary['governance_package'], $includePii)
: [];
$controlInterpretation = is_array($reviewSummary['control_interpretation'] ?? null)
? $reviewSummary['control_interpretation']
: [];
$nonCertificationDisclosure = $this->plainText(
$controlInterpretation['non_certification_disclosure'] ?? null,
'TenantPilot interprets available evidence for review readiness. This is not a certification, legal attestation, or compliance guarantee.',
);
$tenantName = $includePii ? $tenant->name : '[REDACTED]';
$topFindings = is_array($package['top_findings'] ?? null) ? $package['top_findings'] : [];
$acceptedRisks = is_array($package['accepted_risks'] ?? null) ? $package['accepted_risks'] : [];
$governanceDecisions = is_array($package['governance_decisions'] ?? null) ? $package['governance_decisions'] : [];
$nextActions = is_array($reviewSummary['recommended_next_actions'] ?? null) ? $reviewSummary['recommended_next_actions'] : [];
$lines = [
'# Executive summary',
'',
'Tenant: '.$this->plainText($tenantName, '[REDACTED]'),
'Released review: #'.((int) $review->getKey()),
'Review status: '.$this->plainText($review->status, 'unknown'),
'Generated at: '.$generatedAt->toIso8601String(),
'',
'## Executive story',
'',
$this->plainText($package['executive_summary'] ?? null, 'No executive summary is available for this released review.'),
'',
'## Evidence basis',
'',
$this->plainText(
$package['evidence_basis_summary'] ?? null,
sprintf('Anchored to evidence snapshot #%d with %s completeness.', (int) $snapshot->getKey(), (string) $snapshot->completeness_state),
),
'',
'## Key findings',
'',
...$this->entryBullets($topFindings, 'No key findings are listed for this released review.'),
'',
'## Accepted risks',
'',
...$this->entryBullets($acceptedRisks, 'No accepted risks are listed for this released review.'),
'',
'## Governance decisions requiring awareness',
'',
...$this->entryBullets($governanceDecisions, 'No governance decisions require awareness in this released review.'),
'',
'## Next actions',
'',
...$this->textBullets($nextActions, 'No next action is listed for this released review.'),
'',
'## Non-certification disclosure',
'',
$nonCertificationDisclosure,
'',
'## Structured auditor appendix',
'',
'This executive entrypoint is the first file to read. The structured auditor appendix remains available in metadata.json, summary.json, and sections.json.',
'',
];
return implode("\n", $lines);
}
/**
* @param array<int, mixed> $entries
* @return list<string>
*/
private function entryBullets(array $entries, string $emptyText): array
{
if ($entries === []) {
return ['- '.$emptyText];
}
return collect($entries)
->filter(static fn (mixed $entry): bool => is_array($entry))
->map(function (array $entry): string {
$title = $this->plainText($entry['title'] ?? null, 'Entry');
$summary = $this->plainText($entry['summary'] ?? null, '');
return $summary === '' ? '- '.$title : '- '.$title.' - '.$summary;
})
->values()
->all();
}
/**
* @param array<int, mixed> $entries
* @return list<string>
*/
private function textBullets(array $entries, string $emptyText): array
{
$bullets = collect($entries)
->filter(static fn (mixed $entry): bool => is_string($entry) && trim($entry) !== '')
->map(fn (string $entry): string => '- '.$this->plainText($entry, ''))
->values()
->all();
return $bullets === [] ? ['- '.$emptyText] : $bullets;
}
private function plainText(mixed $value, string $fallback): string
{
if (! is_scalar($value) && $value !== null) {
return $fallback;
}
$text = preg_replace('/\s+/', ' ', trim((string) $value));
return is_string($text) && $text !== '' ? $text : $fallback;
}
private function markFailed(ReviewPack $reviewPack, OperationRun $operationRun, OperationRunService $operationRunService, string $reasonCode, string $errorMessage): void
{
$reviewPack->update([

View File

@ -26,6 +26,10 @@
class ReviewPackService
{
public const string REVIEW_DERIVED_DELIVERY_CONTRACT = 'auditor_ready_executive_export.v1';
public const string EXECUTIVE_ENTRYPOINT_FILENAME = 'executive-summary.md';
public function __construct(
private OperationRunService $operationRunService,
private EvidenceSnapshotResolver $snapshotResolver,
@ -193,6 +197,11 @@ public function generateFromReview(TenantReview $review, User $user, array $opti
'review_status' => (string) $review->status,
'review_completeness_state' => (string) $review->completeness_state,
'section_count' => $review->sections->count(),
'delivery_bundle' => [
'contract' => self::REVIEW_DERIVED_DELIVERY_CONTRACT,
'executive_entrypoint_file' => self::EXECUTIVE_ENTRYPOINT_FILENAME,
'appendix_files' => ['metadata.json', 'summary.json', 'sections.json'],
],
'finding_outcomes' => is_array($review->summary['finding_outcomes'] ?? null)
? $review->summary['finding_outcomes']
: [],
@ -376,6 +385,7 @@ public function computeFingerprintForReview(TenantReview $review, array $options
'tenant_review_id' => (int) $review->getKey(),
'review_fingerprint' => (string) $review->fingerprint,
'review_status' => (string) $review->status,
'delivery_contract' => self::REVIEW_DERIVED_DELIVERY_CONTRACT,
'include_pii' => (bool) ($options['include_pii'] ?? true),
'include_operations' => (bool) ($options['include_operations'] ?? true),
];

View File

@ -130,8 +130,8 @@
'customer_reviews' => 'Kundenreviews',
'customer_review_workspace' => 'Kundenreview-Workspace',
'customer_safe_review_workspace' => 'Kundensicherer Governance-Paket-Index',
'customer_workspace_intro' => 'Prüfen Sie für jeden berechtigten Tenant den aktuellen Status des Governance-Pakets und öffnen Sie bei Bedarf die kundensichere Detailansicht.',
'customer_workspace_canonical_note' => 'Jede Zeile ist ein Einstieg in die Detailansicht: Dort sehen Sie Paketstatus, Nachweise, aktuelle Risiken und den nächsten kundensicheren Schritt.',
'customer_workspace_intro' => 'Prüfen Sie für jeden berechtigten Tenant den executive-fähigen Status des Governance-Pakets und öffnen Sie bei Bedarf die kundensichere Detailansicht.',
'customer_workspace_canonical_note' => 'Jede Zeile ist ein Einstieg in die Detailansicht: Dort sehen Sie Paketstatus, Executive-Einstieg, Nachweise, aktuelle Risiken und den nächsten kundensicheren Schritt.',
'customer_workspace_mapping_version' => 'Die Control-Readiness-Interpretation verwendet :version für diesen Workspace.',
'customer_workspace_non_certification_disclosure' => 'Dieser Workspace fasst die aktuelle Review- und Nachweislage für die Service-Auslieferung zusammen. Er ersetzt weder ein formales Auditurteil noch eine Zertifizierung oder rechtliche Attestierung.',
'reviews' => 'Reviews',
@ -173,6 +173,10 @@
'governance_package' => 'Governance-Paket',
'governance_decisions' => 'Governance-Entscheidungen',
'governance_package_delivery_note' => 'Dieses Governance-Paket wird über das aktuelle Export-Review-Pack des veröffentlichten Reviews ausgeliefert.',
'executive_entrypoint' => 'Executive-Einstieg',
'executive_entrypoint_description' => 'Beginnen Sie im heruntergeladenen Paket mit executive-summary.md.',
'auditor_appendix' => 'Strukturierter Auditor-Anhang',
'auditor_appendix_description' => 'metadata.json, summary.json und sections.json bleiben als sekundärer strukturierter Anhang enthalten.',
'governance_package_available' => 'Governance-Paket verfügbar',
'governance_package_available_description' => 'Das aktuelle Export-Review-Pack ist aus diesem veröffentlichten Review für die Stakeholder-Auslieferung bereit.',
'governance_package_partial' => 'Governance-Paket partiell',

View File

@ -130,8 +130,8 @@
'customer_reviews' => 'Customer reviews',
'customer_review_workspace' => 'Customer Review Workspace',
'customer_safe_review_workspace' => 'Customer-safe governance package index',
'customer_workspace_intro' => 'Review the current governance package status for each entitled tenant and open the customer-safe detail when follow-up is needed.',
'customer_workspace_canonical_note' => 'Each row is an index entry: open the review detail to inspect package status, supporting evidence, current risks, and the next customer-safe action.',
'customer_workspace_intro' => 'Review the executive-ready governance package status for each entitled tenant and open the customer-safe detail when follow-up is needed.',
'customer_workspace_canonical_note' => 'Each row is an index entry: open the review detail to inspect package status, the executive entrypoint, supporting evidence, current risks, and the next customer-safe action.',
'customer_workspace_mapping_version' => 'Control readiness interpretation uses :version for this workspace.',
'customer_workspace_non_certification_disclosure' => 'This workspace summarizes current review evidence for service delivery. It does not replace a formal audit opinion, certification, or legal attestation.',
'reviews' => 'Reviews',
@ -173,6 +173,10 @@
'governance_package' => 'Governance package',
'governance_decisions' => 'Governance decisions',
'governance_package_delivery_note' => 'This governance package is delivered through the current export review pack for the released review.',
'executive_entrypoint' => 'Executive entrypoint',
'executive_entrypoint_description' => 'Start with executive-summary.md in the downloaded package.',
'auditor_appendix' => 'Structured auditor appendix',
'auditor_appendix_description' => 'metadata.json, summary.json, and sections.json remain included as the secondary structured appendix.',
'governance_package_available' => 'Governance package available',
'governance_package_available_description' => 'The current export review pack is ready for stakeholder delivery from this released review.',
'governance_package_partial' => 'Governance package partial',

View File

@ -126,12 +126,22 @@
<div class="mt-1 text-sm font-medium text-gray-900 dark:text-gray-100">{{ __('localization.review.download_governance_package') }}</div>
</div>
<div class="rounded-md border border-gray-100 bg-gray-50 px-3 py-2 dark:border-gray-800 dark:bg-gray-950/60">
<div class="text-[11px] font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">{{ __('localization.review.executive_entrypoint') }}</div>
<div class="mt-1 text-sm text-gray-900 dark:text-gray-100">{{ __('localization.review.executive_entrypoint_description') }}</div>
</div>
@if ($packageNextStep !== null)
<div class="rounded-md border border-primary-100 bg-primary-50 px-3 py-2 dark:border-primary-900/40 dark:bg-primary-950/30">
<div class="text-[11px] font-semibold uppercase tracking-wide text-primary-700 dark:text-primary-200">{{ __('localization.review.next_step') }}</div>
<div class="mt-1 text-sm text-primary-900 dark:text-primary-100">{{ $packageNextStep }}</div>
</div>
@endif
<div class="rounded-md border border-gray-100 bg-gray-50 px-3 py-2 dark:border-gray-800 dark:bg-gray-950/60">
<div class="text-[11px] font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">{{ __('localization.review.auditor_appendix') }}</div>
<div class="mt-1 text-sm text-gray-700 dark:text-gray-300">{{ __('localization.review.auditor_appendix_description') }}</div>
</div>
</div>
@if (filled($governancePackage['executive_summary'] ?? null))

View File

@ -88,6 +88,7 @@
->assertSee('Governance package')
->assertSee('Status')
->assertSee('Evidence')
->assertSee('Review the executive-ready governance package status')
->assertSee('This workspace summarizes current review evidence for service delivery. It does not replace a formal audit opinion, certification, or legal attestation.')
->assertSee('Partial')
->assertSee('Review required')
@ -109,6 +110,8 @@
->assertSee('Released governance record')
->assertSee('Review status')
->assertSee('Primary action')
->assertSee('Executive entrypoint')
->assertSee('Structured auditor appendix')
->assertSee('Assessment basis')
->assertDontSee('Control readiness interpretation')
->assertDontSee('Compliance evidence mapping v1')

View File

@ -28,7 +28,7 @@
app()->call([$job, 'handle']);
$pack->refresh();
$review->refresh();
$review->refresh()->load('evidenceSnapshot');
expect($pack->tenant_review_id)->toBe((int) $review->getKey())
->and($pack->status)->toBe(ReviewPackStatus::Ready->value)
@ -47,11 +47,22 @@
$metadata = json_decode((string) $zip->getFromName('metadata.json'), true, 512, JSON_THROW_ON_ERROR);
$summary = json_decode((string) $zip->getFromName('summary.json'), true, 512, JSON_THROW_ON_ERROR);
$sections = json_decode((string) $zip->getFromName('sections.json'), true, 512, JSON_THROW_ON_ERROR);
$executiveEntrypoint = (string) $zip->getFromName(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME);
expect(data_get($metadata, 'tenant_name'))->toBe('[REDACTED]')
->and(data_get($metadata, 'delivery_bundle.entrypoint.file'))->toBe(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME)
->and(data_get($metadata, 'delivery_bundle.entrypoint.role'))->toBe('executive_entrypoint')
->and(data_get($metadata, 'delivery_bundle.appendix.0.file'))->toBe('metadata.json')
->and(data_get($metadata, 'delivery_bundle.appendix.1.file'))->toBe('summary.json')
->and(data_get($metadata, 'delivery_bundle.appendix.2.file'))->toBe('sections.json')
->and(data_get($metadata, 'options.include_operations'))->toBeFalse()
->and(data_get($summary, 'delivery_bundle.executive_entrypoint_file'))->toBe(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME)
->and(data_get($summary, 'tenant_review_id'))->toBe((int) $review->getKey())
->and(collect($sections)->pluck('section_key')->all())->not->toContain('operations_health');
->and(collect($sections)->pluck('section_key')->all())->not->toContain('operations_health')
->and($executiveEntrypoint)->toContain('Tenant: [REDACTED]')
->and($executiveEntrypoint)->toContain('This executive entrypoint is the first file to read')
->and($executiveEntrypoint)->not->toContain((string) $review->fingerprint)
->and($executiveEntrypoint)->not->toContain((string) $review->evidenceSnapshot?->fingerprint);
$zip->close();
unlink($tempFile);

View File

@ -92,7 +92,8 @@
->assertCanSeeTableRecords([$tenantA->fresh(), $tenantB->fresh()])
->assertCanNotSeeTableRecords([$tenantDenied->fresh()])
->assertSee(TenantReviewResource::tenantScopedUrl('view', ['record' => $latestPublishedReview->fresh()], $tenantA), false)
->assertSee('Review the current governance package status for each entitled tenant and open the customer-safe detail when follow-up is needed.')
->assertSee('Review the executive-ready governance package status for each entitled tenant and open the customer-safe detail when follow-up is needed.')
->assertSee('Each row is an index entry: open the review detail to inspect package status, the executive entrypoint, supporting evidence, current risks, and the next customer-safe action.')
->assertSee('This workspace summarizes current review evidence for service delivery. It does not replace a formal audit opinion, certification, or legal attestation.')
->assertSee('Governance package')
->assertSee('Status')

View File

@ -38,7 +38,7 @@
app()->call([$job, 'handle']);
$pack->refresh();
$review->refresh()->load('sections');
$review->refresh()->load(['sections', 'evidenceSnapshot']);
$zipContent = Storage::disk('exports')->get((string) $pack->file_path);
$tempFile = tempnam(sys_get_temp_dir(), 'tenant-review-pack-');
@ -47,13 +47,37 @@
$zip = new ZipArchive;
$zip->open($tempFile);
$metadata = json_decode((string) $zip->getFromName('metadata.json'), true, 512, JSON_THROW_ON_ERROR);
$summary = json_decode((string) $zip->getFromName('summary.json'), true, 512, JSON_THROW_ON_ERROR);
$sections = json_decode((string) $zip->getFromName('sections.json'), true, 512, JSON_THROW_ON_ERROR);
$executiveEntrypoint = (string) $zip->getFromName(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME);
$filenames = collect(range(0, $zip->numFiles - 1))
->map(fn (int $index): string => (string) $zip->getNameIndex($index))
->values()
->all();
expect(array_column($sections, 'section_key'))
->toBe($review->sections->pluck('section_key')->values()->all())
->and($summary['highlights'] ?? null)->toBe($review->summary['highlights'] ?? [])
->and($summary['recommended_next_actions'] ?? null)->toBe($review->summary['recommended_next_actions'] ?? []);
->and($summary['recommended_next_actions'] ?? null)->toBe($review->summary['recommended_next_actions'] ?? [])
->and($summary['delivery_bundle']['contract'] ?? null)->toBe(ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT)
->and($summary['delivery_bundle']['executive_entrypoint_file'] ?? null)->toBe(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME)
->and($metadata['delivery_bundle']['contract'] ?? null)->toBe(ReviewPackService::REVIEW_DERIVED_DELIVERY_CONTRACT)
->and($metadata['delivery_bundle']['review_pack_id'] ?? null)->toBe((int) $pack->getKey())
->and($metadata['delivery_bundle']['released_review']['id'] ?? null)->toBe((int) $review->getKey())
->and($metadata['delivery_bundle']['interpretation_version'] ?? null)->toBe($review->controlInterpretationVersion())
->and($metadata['delivery_bundle']['entrypoint']['file'] ?? null)->toBe(ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME)
->and(collect($metadata['delivery_bundle']['appendix'] ?? [])->pluck('file')->all())->toBe(['metadata.json', 'summary.json', 'sections.json'])
->and($filenames)->toContain('metadata.json', 'summary.json', 'sections.json', ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME)
->and(collect($filenames)->filter(fn (string $filename): bool => str_starts_with($filename, 'executive-'))->values()->all())->toBe([ReviewPackService::EXECUTIVE_ENTRYPOINT_FILENAME])
->and($executiveEntrypoint)->toContain('# Executive summary')
->and($executiveEntrypoint)->toContain('## Executive story')
->and($executiveEntrypoint)->toContain('## Structured auditor appendix')
->and($executiveEntrypoint)->toContain('metadata.json, summary.json, and sections.json')
->and($executiveEntrypoint)->not->toContain((string) $review->fingerprint)
->and($executiveEntrypoint)->not->toContain((string) $review->evidenceSnapshot?->fingerprint)
->and($executiveEntrypoint)->not->toContain('Reason owner')
->and($executiveEntrypoint)->not->toContain('Platform reason family');
$zip->close();
unlink($tempFile);

View File

@ -98,6 +98,10 @@
->assertSee('Last review')
->assertSee('Primary action')
->assertSee('Download governance package')
->assertSee('Executive entrypoint')
->assertSee('Start with executive-summary.md in the downloaded package.')
->assertSee('Structured auditor appendix')
->assertSee('metadata.json, summary.json, and sections.json remain included as the secondary structured appendix.')
->assertSee('Anchored to evidence snapshot #')
->assertSee('Assessment basis')
->assertSee('Evidence basis')

View File

@ -0,0 +1,52 @@
# Specification Quality Checklist: Auditor Pack Delivery & Executive Export v1
**Purpose**: Validate specification completeness and repo fit before implementation
**Created**: 2026-05-02
**Feature**: [spec.md](../spec.md)
## Content Quality
- [x] The spec stays on one bounded follow-up over the current `ReviewPack` family instead of inventing a second package domain.
- [x] The spec is product- and behavior-oriented and does not read like an implementation diff.
- [x] The spec explicitly names the current repo-real foundations it builds on: review-pack export, customer review workspace, compliance interpretation, and governance-package delivery.
- [x] Mandatory repo sections for scope, RBAC, disclosure, testing, and proportionality are completed.
## Requirement Completeness
- [x] No `[NEEDS CLARIFICATION]` markers remain.
- [x] Requirements are testable and bounded to one released-review delivery contract.
- [x] The spec explains what remains in scope versus what is intentionally deferred.
- [x] Acceptance scenarios cover export initiation, read-only delivery, and tenant-safe audit or entitlement behavior.
- [x] Edge cases cover missing packs, expired packs, partial evidence, and blocked commercial lifecycle states.
## Candidate Selection Gate
- [x] The selected candidate exists in `docs/product/spec-candidates.md` and `docs/product/roadmap.md`.
- [x] No existing spec package already covers `Auditor Pack Delivery & Executive Export v1` as its own bounded slice.
- [x] Related anchor specs were checked for completion or close-out signals and treated as context only: `109`, `153`, `155`, `258`, `259`, and `260`, with current repo code and tests used as implementation-truth validation for the delta.
- [x] The chosen slice is smaller and higher-priority than the deferred alternatives from the manual-promotion backlog.
## Feature Readiness
- [x] The slice is an explicit delta follow-up over already prepared customer-safe review/package work and stays on one current `ReviewPack` bundle instead of reopening those inherited surfaces wholesale.
- [x] The spec explicitly reuses the current `ReviewPackGenerate` and signed download seams.
- [x] The spec forbids new panel/provider changes, new global-search scope, and new asset strategy.
- [x] The spec keeps one dominant action per current operator/customer surface and does not reopen broader packaging, branding, or recurring-delivery scope.
## Test Governance
- [x] Planned validation stays bounded to existing `TenantReview`, `Reviews`, and `ReviewPack` feature families plus the current customer-review browser smoke.
- [x] No new heavy-governance or new browser family is introduced.
- [x] The runtime proof commands stay consistent across spec, plan, and tasks, while Pint remains standard implementation hygiene.
## Notes
- Reviewed against `docs/product/spec-candidates.md`, `docs/product/roadmap.md`, `docs/product/implementation-ledger.md`, `specs/109-review-pack-export/spec.md`, `specs/153-evidence-domain-foundation/spec.md`, `specs/155-tenant-review-layer/spec.md`, `specs/258-customer-review-productization/spec.md`, `specs/259-compliance-evidence-mapping/spec.md`, `specs/260-governance-service-packaging/spec.md`, current review/review-pack code and tests under `apps/platform`, and `.specify/memory/constitution.md` on 2026-05-02.
- No application implementation was performed while preparing this package.
## Review Outcome
- **Outcome class**: `acceptable-special-case`
- **Outcome**: `keep`
- **Reason**: The spec promotes the highest-priority manual backlog item, now records itself as a delta follow-up over the already prepared review/package foundations, stays on one current artifact family, and narrows the sellability gap to one externally deliverable bundle.
- **Workflow result**: Ready for implementation.

View File

@ -0,0 +1,215 @@
# Implementation Plan: Auditor Pack Delivery & Executive Export v1
**Branch**: `263-auditor-pack-executive-export` | **Date**: 2026-05-02 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/263-auditor-pack-executive-export/spec.md`
## Summary
This is an explicit delta follow-up over Specs 258-260 and the current review-package code path. The existing customer-safe workspace/detail delivery semantics, current operator export initiation, current signed download route, and current governance-package availability states are inherited. The implementation scope is only to make the existing current bundle externally deliverable by adding one human-readable executive entrypoint inside that bundle, making appendix roles explicit, and applying the minimal wording changes needed to explain that new bundle contract. The implementation must stay on current released-review, review-pack, evidence, and interpretation truth with no new artifact family, no new panel, and no new recurring-delivery workflow.
## Inherited Baseline / Explicit Delta
### Inherited baseline
- `CustomerReviewWorkspace` already owns the calm workspace delivery-selection surface.
- released-review detail already owns the customer-safe governance-package summary and signed download action.
- published operator review detail already owns `export_executive_pack` and current `ReviewPackGenerate` initiation.
- the current review-derived ZIP baseline already contains `metadata.json`, `summary.json`, and `sections.json`.
### Explicit delta in this plan
- preserve the existing ZIP baseline entries and add one executive-first entrypoint file
- extend delivery metadata so the preserved ZIP entries are explicitly framed as the structured appendix
- update only the wording on the inherited workspace/detail surfaces that is required to describe the new bundle contract
## Technical Context
**Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4
**Primary Dependencies**: Filament admin surfaces, current `ReviewPackService`, `GenerateReviewPackJob`, `ReviewPackDownloadController`, `TenantReviewComposer`, `ArtifactTruthPresenter`
**Storage**: PostgreSQL plus private `exports` disk for the existing `ReviewPack` ZIP artifact
**Testing**: Pest feature tests plus one bounded browser smoke
**Validation Lanes**: `confidence`, `browser`
**Target Platform**: Existing Laravel admin runtime under `apps/platform`
**Project Type**: Laravel monolith with Filament admin surfaces
**Performance Goals**: No new provider calls, no second generation flow, and no additional queue family beyond the current `ReviewPackGenerate` run
**Constraints**: No new persisted delivery domain, no new panel/provider/assets, no raw internal diagnostics in the executive entrypoint, preserve current `404`/`403` semantics, preserve current signed download path
**Scale/Scope**: One released review at a time, one current export bundle per released review
## UI / Surface Guardrail Plan
- **Guardrail scope**: changed surfaces
- **Native vs custom classification summary**: native Filament surfaces plus one bounded export entrypoint rendered from existing product truth
- **Shared-family relevance**: review-pack delivery, governance-package wording, detail-summary disclosure, download actions
- **State layers in scope**: page, detail, disclosure state
- **Audience modes in scope**: operator-MSP, customer-admin, customer-read-only, auditor-read-only
- **Decision/diagnostic/raw hierarchy plan**: decision-first delivery readiness and executive summary first, diagnostics second, raw/support detail last
- **Raw/support gating plan**: raw provider payloads, fingerprints, and internal reason semantics stay hidden from the executive entrypoint and customer-safe default surfaces
- **One-primary-action / duplicate-truth control**: workspace rows keep `Open review` only; released-review detail keeps one dominant safe download action; operator detail keeps the existing export initiation action
- **Handling modes by drift class or surface**: `report-only` for unchanged operator-only pack detail surfaces; `review-mandatory` for any change that would add a second delivery action or a second package domain
- **Repository-signal treatment**: `review-mandatory`
- **Special surface test profiles**: `shared-detail-family`
- **Required tests or manual smoke**: focused feature coverage plus the existing bounded browser smoke for `CustomerReviewWorkspace`
- **Exception path and spread control**: none; any proposal for a new artifact family, new panel, or PDF engine is a scope split, not an in-feature exception
- **Active feature PR close-out entry**: Smoke Coverage
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes
- **Systems touched**: `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, `ReviewPackService`, `GenerateReviewPackJob`, `ReviewPackDownloadController`, `TenantReviewComposer`, `TenantReviewSectionFactory`, `ArtifactTruthPresenter`, localization files, and current audit IDs
- **Shared abstractions reused**: `ReviewPackService`, current `ReviewPackGenerate` `OperationRun` contract, current signed download controller, `ArtifactTruthPresenter`, `TenantReviewComposer`, `TenantReviewSectionFactory`, and `WorkspaceAuditLogger`
- **New abstraction introduced? why?**: none required by default. If implementation needs one helper to assemble delivery metadata or executive-export markup, it must stay local to current review-pack generation and not become a new export framework.
- **Why the existing abstraction was sufficient or insufficient**: current seams already solve entitlement, review anchoring, and bundle generation. They are only missing an explicit stakeholder-ready entrypoint and explicit appendix framing.
- **Bounded deviation / spread control**: none
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: yes
- **Central contract reused**: existing `ReviewPackGenerate` start UX and terminal notification flow
- **Delegated UX behaviors**: queued toast, dedupe-or-reuse handling, current run completion semantics, and current signed download follow-up stay delegated to existing review-pack infrastructure
- **Surface-owned behavior kept local**: internal published review detail decides when the export action is offered; customer-safe released-review detail remains download-only
- **Queued DB-notification policy**: unchanged from the current review-pack contract
- **Terminal notification path**: unchanged
- **Exception path**: none
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: no
- **Provider-owned seams**: existing provider-specific report names remain appendix-only and secondary
- **Platform-core seams**: delivery wording, evidence-basis wording, and customer-safe summary semantics remain platform-owned
- **Neutral platform terms / contracts preserved**: governance package, released review, evidence basis, delivery readiness, accepted risks, governance decisions
- **Retained provider-specific semantics and why**: provider-specific report or evidence names can remain in the appendix because the appendix is secondary and evidence-oriented, not the primary executive narrative
- **Bounded extraction or follow-up path**: none
## Constitution Check
*GATE: Must pass before implementation begins and again before merge.*
- Inventory-first: unchanged; all delivery content stays derived from current review, evidence snapshot, stored reports, and current review-pack truth
- Read/write separation: write path remains only the current review-pack generation flow; customer-safe delivery remains read-only
- Graph contract path: no Graph calls are added
- Deterministic capabilities: current review and review-pack capability derivation stays authoritative
- RBAC-UX: workspace membership and tenant/review entitlement remain `404` boundaries; current in-scope capability denials remain `403`
- Workspace isolation: unchanged
- Tenant isolation: unchanged
- Run observability: current `ReviewPackGenerate` `OperationRun` path remains the only generation run path; no new run type or queue family is introduced
- OperationRun start UX: existing shared review-pack start UX remains authoritative
- Ops-UX lifecycle and summary counts: unchanged
- Test governance: keep proof bounded to current review, review-pack, and customer-workspace test families plus one existing browser smoke
- Proportionality / persistence / bloat: no new table, new artifact family, or delivery workflow state is allowed
- Shared pattern first: current review-pack export and download paths must be extended instead of bypassed
- Provider boundary: unchanged
- V1 explicitness / few layers: prefer direct extension of current bundle generation and current UI disclosure
- Badge semantics: reuse the current governance-package availability and artifact-truth badge mapping
- Filament-native UI: keep current native Filament pages and detail surfaces; no new custom dashboard shell
- UI/UX surface taxonomy and decision-first operating model: workspace remains registry-first; released-review detail remains package-owning context
- Audience-aware disclosure: executive-ready summary first, appendix second, raw/internal detail hidden by default
- Action-surface discipline: workspace rows keep one open action, released-review detail keeps one dominant download action, operator detail keeps one dominant export action
## Test Governance Check
- **Test purpose / classification by changed surface**: Feature, Browser
- **Affected validation lanes**: `confidence`, `browser`
- **Why this lane mix is the narrowest sufficient proof**: the slice changes bundle contents, delivery wording, and existing actions on current review surfaces. Focused feature coverage plus the current browser smoke are sufficient without widening into heavy-governance or new browser families.
- **Narrowest proving command(s)**:
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantReview/TenantReviewExecutivePackTest.php tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php tests/Feature/TenantReview/TenantReviewAuditLogTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php`
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`
- **Fixture / helper / factory / seed / context cost risks**: reuse current released-review, evidence, and review-pack fixtures only; avoid new seeded report families or provider setup
- **Expensive defaults or shared helper growth introduced?**: no
- **Heavy-family additions, promotions, or visibility changes**: none
- **Surface-class relief / special coverage rule**: `shared-detail-family`
- **Closing validation and reviewer handoff**: reviewers should confirm that one current `ReviewPack` bundle still drives the entire delivery path and that the browser smoke remains bounded to the existing workspace flow
- **Budget / baseline / trend follow-up**: none
- **Review-stop questions**: lane fit, bundle truth staying on current artifact family, raw-detail leakage, and accidental second-delivery-domain drift
- **Escalation path**: none
- **Active feature PR close-out entry**: Smoke Coverage
## Project Structure
### Documentation (this feature)
```text
specs/263-auditor-pack-executive-export/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
└── requirements.md
```
### Source Code (expected implementation surfaces)
```text
apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php
apps/platform/app/Filament/Resources/TenantReviewResource.php
apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php
apps/platform/app/Services/ReviewPackService.php
apps/platform/app/Jobs/GenerateReviewPackJob.php
apps/platform/app/Http/Controllers/ReviewPackDownloadController.php
apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php
apps/platform/app/Services/TenantReviews/TenantReviewComposer.php
apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php
apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php
apps/platform/resources/views/filament/infolists/entries/tenant-review-summary.blade.php
apps/platform/resources/views/review-packs/...
apps/platform/lang/en/localization.php
apps/platform/lang/de/localization.php
apps/platform/tests/Feature/Reviews/...
apps/platform/tests/Feature/TenantReview/...
apps/platform/tests/Feature/ReviewPack/...
apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php
```
**Structure Decision**: keep the implementation inside the existing admin-plane review and review-pack surfaces. If a dedicated executive-export Blade template is needed, add it under `apps/platform/resources/views/review-packs/` and keep it local to current `ReviewPack` generation.
## Data / Migration Implications
- Prefer extending current bundle contents and current JSON metadata over schema changes.
- Preserve the current review-derived ZIP baseline entries `metadata.json`, `summary.json`, and `sections.json`; the new contract adds one executive-first entrypoint and explicit appendix-role metadata over that baseline.
- No new `ReviewPack` table columns, no new delivery table, and no new artifact registry should be required for v1.
- If implementation cannot express delivery metadata inside the current pack contents or current JSON summary surfaces, stop and split rather than widening persistence scope.
## Rollout Considerations
- Filament remains v5 on Livewire v4. No panel-provider change is required, and provider registration remains in `apps/platform/bootstrap/providers.php`.
- No global search change is required because the affected surfaces stay on existing pages and non-globally-searchable resources.
- No destructive action is added. Existing export generation and download paths remain the only user-triggered flows.
- No new asset registration is expected; any human-readable executive entrypoint should be rendered from existing server-side view capabilities and included in the current bundle.
## Risk Controls
- Reject any implementation that introduces a second delivery artifact family or a new export registry.
- Reject any implementation that adds PDF/report-engine infrastructure or recurring delivery automation in this slice.
- Reject any implementation that exposes raw provider payloads or internal reason ownership in the executive entrypoint.
- Keep customer-safe read-only download semantics and current operator-side export initiation separate.
## Implementation Phases
### Phase 0 - Confirm Current Delivery Truth
- Verify the current review-derived pack contents and metadata contract in `ReviewPackService`, `GenerateReviewPackJob`, and current review-pack tests.
- Verify the current customer-workspace and released-review detail delivery semantics in `CustomerReviewWorkspace`, `ViewTenantReview`, and their tests.
### Phase 1 - Extend The Current Bundle
- Add one human-readable executive entrypoint file to the current review-derived bundle.
- Extend bundle metadata so the executive entrypoint and appendix roles are explicit.
- Keep the current structured appendix files intact and secondary.
### Phase 2 - Align Surfaces With The Delivery Contract
- Update workspace and released-review detail copy so readiness, evidence basis, and delivery wording reflect the new bundle contract.
- Keep `Open review` and `Download governance package` as the dominant safe actions in their existing contexts.
### Phase 3 - Harden Audit, Permissions, And Download Continuity
- Reuse current audit events and signed download controller.
- Confirm export initiation and ready-pack download continue to follow current capability and entitlement rules.
### Phase 4 - Validate And Stop
- Run the planned `confidence` proof and the existing browser smoke.
- Verify no new run type, no new artifact family, no new panel/provider/assets, and no raw-detail leakage.
## Why This Plan Is Narrow Enough
The repo already has a generated review-pack artifact, an operator export action, a customer-safe download action, and shared governance-package meaning. This plan changes only the delivery contract of that existing artifact and the wording on the two existing review surfaces that expose it. Everything broader stays explicitly deferred.

View File

@ -0,0 +1,308 @@
# Feature Specification: Auditor Pack Delivery & Executive Export v1
**Feature Branch**: `263-auditor-pack-executive-export`
**Created**: 2026-05-02
**Status**: Ready for implementation
**Input**: User description: "Promote the top manual backlog item from `docs/product/spec-candidates.md` and `docs/product/roadmap.md` into a new Spec Kit package that turns current review-pack and governance-package truth into one auditor-ready and executive-readable delivery bundle without reopening the existing review, evidence, compliance-mapping, or governance-packaging foundations."
## Inherited Baseline / Explicit Delta
This package is an explicit delta follow-up over already prepared and partly repo-real foundations, especially `specs/109-review-pack-export/spec.md`, `specs/153-evidence-domain-foundation/spec.md`, `specs/155-tenant-review-layer/spec.md`, `specs/258-customer-review-productization/spec.md`, `specs/259-compliance-evidence-mapping/spec.md`, and `specs/260-governance-service-packaging/spec.md`.
Inherited baseline for 263:
- current customer-safe workspace and released-review delivery semantics remain owned by Specs 258-260 and current code
- current operator-side `export_executive_pack` generation path remains owned by the existing review-pack export contract
- current signed review-pack download route remains the only download seam
- current governance-package availability states remain the baseline delivery-state model
New delta introduced by 263 only:
- add one explicit executive-first entrypoint inside the current review-derived pack
- add explicit bundle metadata clarifying which current files form the structured auditor appendix
- make only the minimal workspace/detail wording changes required to describe that new bundle contract
Everything broader stays inherited and out of scope unless it must change solely to explain the new bundle artifact.
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: TenantPilot already has a review-derived export path (`export_executive_pack`), a ready or partial governance-package surface in the customer review workspace, current signed review-pack downloads, and shared compliance interpretation. What is still missing is one explicitly audience-ordered delivery artifact that an operator can hand to executives or auditors without manually explaining which parts of the current review pack are safe for whom.
- **Today's failure**: Published reviews can already produce or reuse a review-derived pack, but the exported artifact still reads like a product-internal review pack rather than an externally deliverable package. Operators still need ad-hoc guidance outside the product to explain the executive story, the evidence basis, and which files form the auditor appendix.
- **User-visible improvement**: An entitled actor can open one released review context and download one clearly packaged bundle whose default entrypoint is executive-readable while the structured appendix remains available for auditor follow-up inside the same delivery path.
- **Smallest enterprise-capable version**: Keep one released-review-bound `ReviewPack` artifact and the current signed download seam. Extend that existing bundle with one human-readable executive export entrypoint plus explicit delivery metadata that explains the included auditor appendix files. No new package domain, no new panel, no new scheduling, no new customer portal, and no second artifact family ship in v1.
- **Explicit non-goals**: No standalone `AuditorPack` model or table, no new report engine, no PDF renderer requirement, no campaign or recurring delivery workflow, no email delivery automation, no branding or white-label system, no multi-review or multi-tenant package batch, no new review publication workflow, and no raw provider-payload dump as the default human-readable export.
- **Permanent complexity imported**: One bounded delivery-bundle contract over the existing `ReviewPack` artifact, one export-ready summary template or equivalent presentation layer for the executive entrypoint, localized copy updates, and focused feature plus browser coverage. No new persisted workflow state is introduced.
- **Why now**: `docs/product/roadmap.md` and `docs/product/spec-candidates.md` both rank this as the highest-priority manual-promotion gap, and `docs/product/implementation-ledger.md` still marks auditor-ready executive delivery as the clearest remaining blocker between repo-real review truth and a repeatable sellable outcome.
- **Why not local**: A local copy tweak on the customer review workspace or a one-off download rename would not turn the current artifact into a credible external deliverable. A larger portal or reporting engine would overshoot the repo's current need.
- **Approval class**: Core Enterprise
- **Red flags triggered**: New delivery vocabulary and export-bundle expectations over an existing artifact family. Defense: the slice stays fully derived from `TenantReview`, `ReviewPack`, `EvidenceSnapshot`, and shared interpretation truth; it does not add new persistence, new workflow state, or a second export subsystem.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: canonical-view
- **Primary Routes**:
- existing workspace customer review registry at `/admin/reviews/workspace`
- existing tenant-scoped released review detail route under `TenantReviewResource`
- existing signed review-pack download route used by the current governance-package download path
- existing operator-side published review detail export action on `ViewTenantReview`
- **Data Ownership**:
- `TenantReview`, `ReviewPack`, `EvidenceSnapshot`, `StoredReport`, `Finding`, `FindingException`, `FindingExceptionDecision`, and `AuditLog` remain the only persisted truth used by this slice
- the delivered auditor-ready bundle remains one `ReviewPack` artifact tied to one released review; no new `AuditorPack`, `ExecutiveExport`, or delivery-campaign persistence family is introduced
- v1 should prefer extending bundle contents and current `metadata.json` / `summary` data over adding new database columns; if implementation cannot stay inside existing artifact and JSON surfaces, it must stop and split scope
- **RBAC**:
- workspace membership remains the first isolation boundary and stays `404` for non-members or out-of-scope tenant or review targets
- operator-side export initiation on published review detail continues to require the current review-manage capability path used by `export_executive_pack`
- read-only delivery download continues to reuse current released-review and review-pack visibility rules on the customer-safe detail route and signed download endpoint
- in-scope capability denials remain `403` only where the current review or review-pack contract already does so; this slice must not invent a new capability family for auditor or executive delivery
- the slice remains read-only for the customer-safe flow and does not introduce destructive actions
For canonical-view specs, the spec MUST define:
- **Default filter behavior when tenant-context is active**: `CustomerReviewWorkspace` keeps the current tenant-prefilter launch behavior. When launched from a tenant-context surface, the workspace prefilters to that tenant and opens the latest released review as the delivery context.
- **Explicit entitlement checks preventing cross-tenant leakage**: package availability, executive-export readiness, and review-pack access signals remain derived only for entitled tenants and released reviews. Inaccessible targets are omitted from aggregate lists and direct targeting resolves as not found.
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
- **Cross-cutting feature?**: yes
- **Interaction class(es)**: download actions, delivery-status messaging, management-summary disclosure, review-pack delivery framing, navigation entry points, and audit-backed export/download flows
- **Systems touched**: `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, `ReviewPackService`, `ReviewPackDownloadController`, `GenerateReviewPackJob`, `TenantReviewComposer`, `TenantReviewSectionFactory`, `ArtifactTruthPresenter`, localization files, and existing audit infrastructure
- **Existing pattern(s) to extend**: current `export_executive_pack` generation path, current `download_current_review_pack` customer-safe action, current governance-package availability states, current signed download route, and the existing released-review detail summary contract
- **Shared contract / presenter / builder / renderer to reuse**: `ReviewPackService`, `ArtifactTruthPresenter`, `TenantReviewComposer`, `TenantReviewSectionFactory`, `ReviewPackDownloadController`, `WorkspaceAuditLogger`, and the current review-pack action and resource seams
- **Why the existing shared path is sufficient or insufficient**: the existing path is already sufficient for review anchoring, entitlement enforcement, current package readiness states, and signed download handling. It is insufficient only because the bundle itself still lacks an explicit executive entrypoint and explicit explanation of which files form the auditor appendix.
- **Allowed deviation and why**: none. The slice must extend the current review-pack family and current released-review surfaces instead of introducing a second package domain or a new export framework.
- **Consistency impact**: `Governance package`, `Export executive pack`, delivery availability labels, evidence-basis wording, and non-certification disclosure must stay aligned across workspace rows, released review detail, exported bundle metadata, and signed download copy.
- **Review focus**: reviewers must block any second artifact family, any direct raw-report export that bypasses released-review truth, any portal-specific duplication of package status, or any scope growth into recurring delivery automation.
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
- **Touches OperationRun start/completion/link UX?**: yes
- **Shared OperationRun UX contract/layer reused**: the existing `ReviewPackGenerate` start and completion flow reused by `TenantReviewResource::executeExport()` remains the only run path
- **Delegated start/completion UX behaviors**: queued toast, already-available pack reuse, active-run dedupe messaging, existing terminal `OperationRunCompleted` delivery, and current signed-download follow-up stay on the shared review-pack export path
- **Local surface-owned behavior that remains**: the internal published review detail continues to decide when `export_executive_pack` is visible or primary; the customer-safe released-review detail continues to expose download only when a ready pack already exists
- **Queued DB-notification policy**: unchanged from the current review-pack export contract
- **Terminal notification path**: unchanged; the current `OperationRunCompleted` path remains authoritative
- **Exception required?**: none
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
N/A - no shared provider/platform seam is widened. Provider-specific report names and evidence details remain secondary appendix content and do not become the primary delivery language.
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Customer Review Workspace page | yes | Native Filament page plus shared review-package primitives | delivery availability, package wording, navigation entry points | page, table, disclosure state | no | Existing row action remains `Open review`; delivery state stays informational on the workspace surface |
| Released review detail in customer-workspace mode | yes | Native Filament detail surface plus shared summary and artifact-truth primitives | delivery summary, package entrypoint, appendix disclosure | detail sections, disclosure state | no | Existing `Download governance package` remains the dominant safe action |
| Published review detail in operator mode | yes | Native Filament detail surface | export initiation, queued/reused package messaging | header actions, detail context | no | Existing `export_executive_pack` initiation path remains the only generation entrypoint |
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Customer Review Workspace page | Primary Decision Surface | Operator decides which released review is ready for external delivery | released review state, package readiness, evidence-basis presence, and current next step | released review detail and appendix context after explicit open | Primary because it remains the calm workspace selection surface for customer-safe delivery | Keeps delivery anchored to the existing review-consumption workflow | Removes the need to inspect operator-only review-pack pages before the first decision |
| Released review detail in customer-workspace mode | Secondary Context | Operator or entitled reader confirms what the delivered bundle means and downloads it | executive-ready summary, evidence basis, package readiness, and the dominant download action | appendix semantics, deeper proof links, and review lineage after explicit drilldown | Secondary because the review has already been selected on the workspace surface | Keeps delivery centered on one released review | Avoids duplicate summaries across workspace and detail surfaces |
| Published review detail in operator mode | Secondary Context | Operator decides whether to generate or reuse the current export bundle | current review status, export readiness, and queued/reused package outcome | review-pack detail or run detail only after explicit follow-up | Secondary because this is the operator-only generation context, not the customer-safe delivery registry | Preserves the current operator workflow while clarifying the final bundle purpose | Prevents the operator from bouncing between review detail and review-pack resource just to know what will be delivered |
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Customer Review Workspace page | operator-MSP, customer-admin, auditor-read-only, customer-read-only | delivery availability, released review state, executive-ready teaser, and evidence-basis presence | none beyond current review state and next-step copy | raw appendix files, provider payloads, fingerprints, and operator-only diagnostics stay off the list surface | `Open review` | raw/support detail stays off the workspace page by default | workspace rows say only whether delivery is ready; detail owns the actual delivery summary |
| Released review detail in customer-workspace mode | operator-MSP, customer-admin, auditor-read-only, customer-read-only | executive summary, evidence basis, top findings, accepted risks, governance decisions requiring awareness, and current delivery readiness | review lineage, interpretation freshness, and artifact availability descriptions in secondary sections only | raw provider payloads, fingerprints, internal reason ownership, and platform reason families stay hidden or gated | `Download governance package` | appendix file structure and operator-only proof links remain secondary | the delivery summary appears once in the governance-package block; later sections add evidence rather than restating the same outcome |
| Published review detail in operator mode | operator-MSP | export readiness, existing package state, and bundle purpose | run details and review-pack detail remain secondary | raw appendix files remain on the pack resource, not the primary review detail block | `Export executive pack` | customer-facing download copy stays off operator-only generation states until a pack is ready | generation context explains bundle purpose once and defers proof to the pack detail or download |
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Customer Review Workspace page | List / Table / Read-only workspace report | Read-only registry report | Open the released review that is ready for delivery | full-row open via the existing `Open review` link | required | no peer download action on the list surface | none | `/admin/reviews/workspace` | existing tenant review detail route | workspace context, tenant prefilter, released review state, delivery availability | Customer review | whether a released review is delivery-ready | none |
| Released review detail in customer-workspace mode | Detail / Report / Management export | Read-only detail report | Download the current governance package | sectioned detail with one dominant safe header action | forbidden | appendix descriptions and proof links remain secondary in-body | none | `/admin/reviews/workspace` | existing tenant review detail route | workspace, tenant, release state, evidence basis, delivery availability | Governance package | what the exported bundle means and whether it is ready | none |
| Published review detail in operator mode | Detail / Report / Export initiation | Operator export surface | Start or reuse the review-derived export bundle | sectioned detail page with one primary export action | forbidden | review-pack detail or run links remain secondary | none | existing tenant review collection route | existing tenant review detail route | tenant context, review status, export readiness | Executive pack export | whether an export can start or be reused now | none |
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Customer Review Workspace page | MSP operator or entitled reviewer | Decide which released review is ready for stakeholder delivery | Read-only workspace review overview | Which released review can I safely deliver right now? | released review state, delivery availability, evidence-basis presence, and next step | none beyond secondary review detail | release state, delivery readiness, evidence sufficiency | none | Open review | none |
| Released review detail in customer-workspace mode | MSP operator, customer admin, auditor with read access | Understand the delivery package and download it | Read-only detail report | What will this delivery bundle say, and is it ready? | executive summary, evidence basis, top findings, accepted risks, governance decisions, and delivery status | appendix structure, deeper evidence links, and lineage | delivery readiness, evidence sufficiency, released review status | none | Download governance package | none |
| Published review detail in operator mode | MSP operator | Generate or reuse the review-derived delivery bundle | Detail/export initiation surface | Can I prepare the current delivery bundle now, or is one already available? | review status, export readiness, and package reuse status | run detail and review-pack detail after explicit follow-up | review status, generation readiness, package availability | current `ReviewPackGenerate` run only | Export executive pack | none |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no
- **New persisted entity/table/artifact?**: no new persisted family; the existing `ReviewPack` artifact remains the delivery artifact
- **New abstraction?**: no new cross-domain abstraction by default; any implementation helper must stay local to current review-pack generation and delivery seams
- **New enum/state/reason family?**: no
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: the repo can already generate a review-derived export and show a customer-safe governance-package summary, but it still cannot hand over one clearly audience-ordered delivery artifact without manual explanation.
- **Existing structure is insufficient because**: the current bundle is machine-oriented and the current UI summary is in-app only. Neither alone gives a stakeholder-ready delivery contract.
- **Narrowest correct implementation**: extend the existing review-derived `ReviewPack` bundle and current signed download path with one human-readable executive entrypoint and explicit delivery metadata instead of creating a second package family.
- **Ownership cost**: maintain one additional exported entrypoint, one bundle metadata contract, a small amount of localized copy, and focused delivery tests.
- **Alternative intentionally rejected**: a standalone `AuditorPack` domain, a PDF/reporting engine, or recurring delivery automation were rejected as broader than current-release truth requires.
- **Release truth**: current-release sellability follow-through, not future-release delivery automation.
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical extension of the current `ReviewPack` bundle is preferred over adding a new delivery artifact family.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Feature, Browser
- **Validation lane(s)**: confidence, browser
- **Why this classification and these lanes are sufficient**: focused feature tests prove bundle contents, current export reuse, signed-download continuity, customer-safe disclosure, and entitlement boundaries on the current review and review-pack surfaces. One bounded browser smoke remains justified because the customer-facing detail copy and dominant action are user-visible delivery surfaces.
- **New or expanded test families**: extend existing `apps/platform/tests/Feature/TenantReview/`, `apps/platform/tests/Feature/Reviews/`, and `apps/platform/tests/Feature/ReviewPack/` families plus the existing `apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`
- **Fixture / helper cost impact**: low to moderate; reuse current released-review, evidence-snapshot, review-pack, and entitlement fixtures. No provider-sync, no new queue family, and no heavy-governance lane are needed.
- **Heavy-family visibility / justification**: none
- **Special surface test profile**: shared-detail-family
- **Standard-native relief or required special coverage**: customer-workspace list behavior keeps standard native coverage; the released-review detail and bundle contract need explicit shared-detail coverage plus the existing browser smoke
- **Reviewer handoff**: reviewers must confirm that the exported bundle stays on the current `ReviewPack` family, the executive entrypoint is human-readable and customer-safe, the appendix stays clearly secondary, the workspace surface keeps `Open review` as the only dominant row action, and no second delivery domain or new run type appears
- **Budget / baseline / trend impact**: low feature-local increase only
- **Escalation needed**: none
- **Active feature PR close-out entry**: Smoke Coverage
- **Planned validation commands**:
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantReview/TenantReviewExecutivePackTest.php tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php tests/Feature/TenantReview/TenantReviewAuditLogTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php`
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Deliver One Stakeholder-Ready Bundle From A Released Review (Priority: P1)
As an MSP operator, I want a published review to produce one delivery-ready package that I can hand to an executive or auditor without separately explaining which files matter.
**Why this priority**: This is the commercial core of the slice. Without one externally deliverable bundle, the feature remains an internal review surface only.
**Independent Test**: Trigger `export_executive_pack` for a published review, finish the existing review-pack generation job, download the resulting pack through the current signed download path, and verify that the bundle contains both the current structured appendix files and one human-readable executive entrypoint.
**Acceptance Scenarios**:
1. **Given** a published review with an eligible evidence basis, **When** an entitled operator runs `export_executive_pack`, **Then** the existing `ReviewPackGenerate` flow starts or reuses the current pack and the finished bundle contains one executive entrypoint plus the existing structured appendix files.
2. **Given** a ready current export pack for a released review, **When** an entitled reader opens the customer-safe released-review detail and chooses `Download governance package`, **Then** the same current pack is downloaded through the existing signed route rather than a second artifact family.
3. **Given** the current export pack already exists and is still valid, **When** an operator repeats the export action, **Then** the system reuses the existing pack instead of creating a second delivery artifact.
---
### User Story 2 - Read The Executive Story First And The Auditor Appendix Second (Priority: P1)
As an entitled reviewer, I want the delivered bundle and released-review detail to make the executive summary obvious first while keeping the structured appendix clearly secondary, so the package is usable without exposing internal diagnostics by default.
**Why this priority**: The product already exposes governance-package meaning in-app. The missing value is making that meaning the default entrypoint of the delivered bundle.
**Independent Test**: Open a released review in customer-workspace mode, confirm the default-visible package block is customer-safe and executive-readable, then inspect the downloaded pack to verify the executive entrypoint and appendix roles are explicit.
**Acceptance Scenarios**:
1. **Given** a released review in customer-workspace mode, **When** the detail page renders, **Then** it shows executive-ready summary, evidence basis, delivery readiness, and `Download governance package` without exposing fingerprints, raw payloads, internal reason ownership, or platform reason families by default.
2. **Given** the delivered bundle is opened, **When** the recipient inspects the archive, **Then** the executive entrypoint is obvious and the structured appendix files remain present but secondary.
3. **Given** delivery readiness is `partial`, `unavailable`, `expired`, or `blocked`, **When** the workspace row or detail page renders, **Then** the product explains that state truthfully without pretending a bundle is ready.
---
### User Story 3 - Keep Delivery Tenant-Safe, Auditable, And Bounded (Priority: P2)
As a platform owner, I want the new delivery bundle to stay on the current entitlement, audit, and review-pack seams so the sellability improvement does not create a second uncontrolled export surface.
**Why this priority**: The feature only improves trust if it stays on the current authorization and audit boundaries.
**Independent Test**: Verify non-members receive `404`, in-scope actors use the existing download/export capability paths, and export/download activity remains visible through the existing audit and `OperationRun` seams.
**Acceptance Scenarios**:
1. **Given** a non-member or an out-of-scope tenant or review target, **When** they attempt to open the workspace, released-review detail, or signed download route, **Then** the response remains deny-as-not-found.
2. **Given** an entitled read-only reviewer with access to the released review and current export pack, **When** they download the governance package, **Then** the bundle is accessible without exposing operator-only diagnostics in the default human-readable export.
3. **Given** an entitled operator exports a published review, **When** the bundle is created or reused, **Then** the current audit and `ReviewPackGenerate` observability signals remain intact and no new delivery workflow state is introduced.
### Edge Cases
- What happens when a released review exists but no ready current export pack exists yet? The customer-safe detail stays truthful about unavailability and does not fabricate a download link.
- What happens when the current export pack is expired? The workspace and detail surfaces show `expired`, and the reader must rely on the operator-side generation flow to prepare a new bundle.
- What happens when the released review is customer-safe but some supporting evidence remains partial or stale? The executive entrypoint must say so explicitly, and the bundle stays `partial` rather than falsely `available`.
- What happens when a workspace commercial lifecycle state blocks new export starts but an existing ready pack remains downloadable? The operator-side export action stays blocked while the current allowed download semantics remain intact.
## Requirements *(mandatory)*
**Constitution alignment:** This feature reuses the current `ReviewPackGenerate` `OperationRun` path and existing signed review-pack download route. It must not introduce a second export run type, a second artifact family, or any new write path outside current review-pack generation. UI visibility remains non-authoritative; current `404`/`403` semantics stay enforced server-side.
**Constitution alignment (PROP-001 / PERSIST-001 / BLOAT-001):** This feature must stay on the existing `ReviewPack` persistence family. If implementation requires a new table, new standalone package model, or new delivery workflow state, the scope fails readiness and must split.
**Constitution alignment (XCUT-001):** Delivery status messaging, download actions, and review-pack export reuse must extend the current review, review-pack, and artifact-truth paths rather than introducing a new package presenter stack or a parallel portal UX language.
### Functional Requirements
- **FR-001**: The existing review-derived `ReviewPack` bundle for a published review MUST become the auditor-ready delivery bundle for this slice; no second artifact family may be introduced.
- **FR-002**: Operator-side export initiation for published reviews MUST continue to reuse the current `export_executive_pack` action and current `ReviewPackGenerate` `OperationRun` semantics.
- **FR-003**: Customer-safe read-only download for a released review MUST continue to reuse the current signed review-pack download route reached from `download_current_review_pack`.
- **FR-004**: The delivered bundle MUST preserve the current review-derived ZIP baseline entries `metadata.json`, `summary.json`, and `sections.json`, and MUST add exactly one human-readable executive entrypoint file suitable for executive-first consumption.
- **FR-005**: The delivered bundle metadata MUST explicitly identify the released review context, the current export review pack identity, interpretation version, evidence basis, generation timestamps, and which file is the executive entrypoint versus the preserved appendix entries `metadata.json`, `summary.json`, and `sections.json`.
- **FR-006**: The executive entrypoint MUST be derived from current released-review truth and shared interpretation truth, including executive summary, key findings, accepted risks, governance decisions requiring awareness, evidence basis, and explicit non-certification disclosure.
- **FR-007**: The executive entrypoint MUST NOT expose raw provider payloads, fingerprints, internal reason ownership, platform reason families, or operator-only diagnostics by default.
- **FR-008**: `CustomerReviewWorkspace` and released-review detail MUST keep package availability states truthful (`available`, `partial`, `unavailable`, `expired`, `blocked`) and must not imply delivery readiness when the current pack or evidence basis is not sufficient.
- **FR-009**: The workspace surface MUST keep `Open review` as the only dominant row action. It may not add a peer download action or a second delivery-specific row action.
- **FR-010**: The customer-safe released-review detail MUST keep one dominant safe download action and must present the auditor appendix as secondary explanatory context rather than a competing primary action.
- **FR-011**: Existing export/download audit events and metadata MUST be reused or minimally extended. A new audit family specific to auditor packs is out of scope.
- **FR-012**: This slice MUST NOT add new panel providers, new globally searchable resources, or new asset registration. Existing Filament v5 / Livewire v4 admin surfaces remain the only UI path.
## Scope Boundaries
### In Scope
- one auditor-ready delivery contract over the current review-derived `ReviewPack` bundle
- one human-readable executive entrypoint added to that current bundle while preserving `metadata.json`, `summary.json`, and `sections.json`
- delivery metadata clarifying executive entrypoint versus the preserved appendix roles
- only the truthful package-readiness and delivery wording changes on `CustomerReviewWorkspace` and released-review detail that are required to explain the new bundle contract
- reuse of current operator-side export initiation and current customer-safe signed download path
- focused localization, entitlement, audit, and browser-smoke follow-through for that delivery bundle
### Non-Goals
- a new `AuditorPack` model, table, or standalone delivery registry
- a new report engine, template system, or PDF-generation requirement
- recurring delivery schedules, campaigns, email delivery, or workflow automation
- white-label branding, customer-specific theming, or MSP profile variants
- a portal, new panel, or external identity plane
- multi-review or multi-tenant package batching
- raw provider-payload export as the default executive output
- any new destructive action or approval workflow
## Acceptance Criteria
- A published review can still generate or reuse one current export pack, and that pack now exposes a clear executive entrypoint plus a clearly secondary structured appendix.
- `CustomerReviewWorkspace` remains a calm selection surface with `Open review` as the only dominant row action, while released-review detail remains the package-owning context.
- Customer-safe delivery copy stays derived from existing review and interpretation truth and hides internal operator-only diagnostics by default.
- Existing `ReviewPackGenerate` and signed-download seams remain authoritative; no second artifact family or new run type is introduced.
## Success Criteria
- An operator no longer needs external instructions to explain which file in the current bundle is the executive-first entrypoint.
- An entitled customer-safe reader can download the same current bundle from released-review detail without seeing raw internal diagnostics by default.
- Review-pack delivery becomes closer to auditor-/executive-ready packaging without reopening the already prepared customer-safe workspace/detail delivery semantics from Specs 258-260.
## Assumptions
- The current `ReviewPack` ZIP artifact remains the acceptable v1 delivery container.
- A human-readable executive entrypoint can be produced inside the current export flow without introducing a new rendering subsystem.
- Existing review, review-pack, evidence, and interpretation truth are sufficient for v1 delivery framing; missing or stale basis is handled through truthful readiness states rather than by generating new data.
## Risks
- The slice could drift into a second export domain if implementation treats auditor delivery as a new artifact family instead of extending the current `ReviewPack` bundle.
- Scope pressure could try to add PDF tooling, branding, or recurring delivery automation even though those are explicitly deferred.
- The executive entrypoint could accidentally mirror internal diagnostics unless the delivery copy stays on the existing customer-safe interpretation path.
## Candidate Selection Rationale
- **Selected candidate**: Auditor Pack Delivery & Executive Export v1
- **Source locations**:
- `docs/product/spec-candidates.md`
- `docs/product/roadmap.md`
- `docs/product/implementation-ledger.md`
- **Why selected**: The active queue is intentionally empty, and this is the top-ranked manual-promotion backlog item with no existing spec package. The repo already contains the prerequisite review-pack export, customer review workspace, compliance interpretation, and governance-package delivery foundations.
- **Why close alternatives were deferred**:
- `Cross-Tenant Promotion Execution v1` already has Spec 043 for compare preview and preflight; the remaining gap is a later portfolio-action slice.
- `Governance Decision Pack & Approval Workflow v1` depends on the broader decision-operating lane and is ranked behind auditor-ready delivery in current roadmap order.
- `Customer-Facing Localization Adoption v1`, `Billing & Subscription Truth Layer v1`, `Stored Reports Surface v1`, `Workspace & Tenant Closure Lifecycle v1`, and `First Governed AI Runtime Consumer v1` remain valid manual promotions, but none is ranked above auditor-ready delivery in the current repo-backed backlog.

View File

@ -0,0 +1,184 @@
---
description: "Task list for Auditor Pack Delivery & Executive Export v1"
---
# Tasks: Auditor Pack Delivery & Executive Export v1
**Input**: Design documents from `specs/263-auditor-pack-executive-export/`
**Prerequisites**: `specs/263-auditor-pack-executive-export/spec.md`, `specs/263-auditor-pack-executive-export/plan.md`, `specs/263-auditor-pack-executive-export/checklists/requirements.md`
**Tests**: REQUIRED (Pest). Keep proof bounded to existing `Feature` families around `TenantReview`, `Reviews`, and `ReviewPack`, plus the current `CustomerReviewWorkspace` browser smoke only.
**Operations**: Reuse the existing `ReviewPackGenerate` `OperationRun` path and signed review-pack download route. No new run type, no new queue family, and no new export artifact family are allowed.
**RBAC**: Workspace or tenant non-members remain `404`; current in-scope review/export/download denials remain `403` where the existing review-pack contract already uses them. No new capability family may be introduced.
**Shared Pattern Reuse**: Reuse `CustomerReviewWorkspace`, `TenantReviewResource`, `ViewTenantReview`, `ReviewPackService`, `GenerateReviewPackJob`, `ReviewPackDownloadController`, `TenantReviewComposer`, `TenantReviewSectionFactory`, `ArtifactTruthPresenter`, current localization files, and current audit IDs. Do not create a new `AuditorPack` or reporting subsystem.
**Filament / Panel Guardrails**: Filament remains v5 on Livewire v4. Provider registration remains unchanged in `apps/platform/bootstrap/providers.php`. No new panel, no new globally searchable resource, and no new asset strategy are allowed.
**Organization**: Tasks are grouped by user story so the bundle contract, the delivery disclosure, and the entitlement/audit boundaries stay independently implementable and testable. This package is a delta follow-up over Specs 258-260 and current code; broader customer-safe workspace/detail behavior is inherited unless a task explicitly changes it to explain the new bundle contract.
## Test Governance Checklist
- [x] Lane assignment stays `confidence` plus the existing bounded `browser` smoke and remains the narrowest sufficient proof.
- [x] New or changed tests stay in the existing `apps/platform/tests/Feature/TenantReview/`, `apps/platform/tests/Feature/Reviews/`, and `apps/platform/tests/Feature/ReviewPack/` families plus `apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php`.
- [x] Shared helpers, released-review fixtures, review-pack fixtures, and evidence fixtures stay cheap by default.
- [x] Planned validation commands cover bundle contents, disclosure, download continuity, and entitlement behavior without widening into unrelated lanes.
- [x] The declared surface test profile remains `shared-detail-family`.
- [x] Any drift toward a second artifact family, a PDF engine, or recurring delivery automation is handled as `reject-or-split` or `follow-up-spec`, not hidden inside this feature.
## Phase 1: Setup (Shared Context)
**Purpose**: Confirm the current review-pack bundle, delivery wording, and entitlement seams before any implementation change.
- [x] T001 Review `specs/263-auditor-pack-executive-export/spec.md`, `specs/263-auditor-pack-executive-export/plan.md`, `specs/263-auditor-pack-executive-export/checklists/requirements.md`, `specs/109-review-pack-export/spec.md`, `specs/153-evidence-domain-foundation/spec.md`, `specs/155-tenant-review-layer/spec.md`, `specs/258-customer-review-productization/spec.md`, `specs/259-compliance-evidence-mapping/spec.md`, and `specs/260-governance-service-packaging/spec.md` together so the slice stays on the current bundle and delivery foundations.
- [x] T002 [P] Confirm the current operator export initiation seam in `apps/platform/app/Filament/Resources/TenantReviewResource.php` and `apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php`.
- [x] T003 [P] Confirm the current bundle generation and download seams in `apps/platform/app/Services/ReviewPackService.php`, `apps/platform/app/Jobs/GenerateReviewPackJob.php`, and `apps/platform/app/Http/Controllers/ReviewPackDownloadController.php`.
- [x] T004 [P] Confirm the current customer-safe delivery surfaces in `apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php`, `apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php`, and `apps/platform/resources/views/filament/infolists/entries/tenant-review-summary.blade.php`.
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Lock the bounded delivery contract before surface-level changes begin.
**Critical**: No user-story work should begin until this phase is complete.
- [x] T005 [P] Extend `apps/platform/tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php` and `apps/platform/tests/Feature/TenantReview/TenantReviewExecutivePackTest.php` to require one human-readable executive entrypoint plus explicit delivery metadata inside the current review-derived pack while preserving the current ZIP baseline entries `metadata.json`, `summary.json`, and `sections.json`.
- [x] T006 [P] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php` and `apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php` to prove the feature still reuses the current `ReviewPackGenerate` path and the current signed download route rather than introducing a second artifact or download flow. Existing tests already covered this seam; the validation lane confirmed them unchanged.
- [x] T007 [P] Extend `apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php`, `apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php`, `apps/platform/tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php`, and `apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php` to lock delivery-readiness wording, one dominant action per surface, and the absence of raw/internal detail in the customer-safe default path. New wording/default-disclosure assertions landed in `CustomerReviewWorkspacePageTest` and `TenantReviewExplanationSurfaceTest`; existing pack-access and UI-contract tests remained the action-hierarchy guard.
- [x] T008 Implement the bundle-contract change in `apps/platform/app/Services/ReviewPackService.php` and `apps/platform/app/Jobs/GenerateReviewPackJob.php`, keeping the current `ReviewPack` family and the ZIP baseline entries `metadata.json`, `summary.json`, and `sections.json` intact while adding one executive entrypoint and explicit delivery metadata.
- [x] T009 [P] Add or update the executive-entrypoint presentation layer under `apps/platform/resources/views/review-packs/` only if the current bundle generation cannot render the executive export cleanly from existing summary truth. Not needed: the current job renders a bounded Markdown entrypoint directly from existing review summary truth.
**Checkpoint**: The current bundle, current run path, and current customer-safe surfaces are all locked to the new delivery contract before broader wording changes begin.
---
## Phase 3: User Story 1 - Deliver One Stakeholder-Ready Bundle From A Released Review (Priority: P1)
**Goal**: A published review can generate or reuse one current export bundle that is ready to hand over externally.
**Independent Test**: Export a published review, complete the current generation job, and download the resulting current pack to verify that one executive entrypoint and the existing structured appendix coexist in the same bundle.
### Tests for User Story 1
- [x] T010 [P] [US1] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewExecutivePackTest.php` to assert that the current pack remains review-anchored and now exposes the executive entrypoint plus delivery metadata.
- [x] T011 [P] [US1] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php` to assert that export initiation still uses the existing `ReviewPackGenerate` path, dedupes correctly, and stays on the current operator-side action. Existing coverage already proved the unchanged run path and dedupe behavior.
- [x] T012 [P] [US1] Extend `apps/platform/tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php` and `apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php` to verify the new bundle contents and signed-download continuity. New bundle assertions landed in `TenantReviewDerivedReviewPackTest`; existing download continuity coverage remained unchanged and passed.
### Implementation for User Story 1
- [x] T013 [US1] Update `apps/platform/app/Services/ReviewPackService.php` and `apps/platform/app/Jobs/GenerateReviewPackJob.php` so review-derived packs produce one executive entrypoint and explicit delivery metadata while preserving current appendix files and current `current_export_review_pack_id` behavior.
- [x] T014 [US1] Update `apps/platform/app/Filament/Resources/TenantReviewResource.php` and `apps/platform/app/Filament/Resources/TenantReviewResource/Pages/ViewTenantReview.php` so published-review export continues to generate or reuse the current pack without introducing a second delivery action or a second artifact family. No code update was needed; repo truth already used the current action and run seam, and tests confirmed it.
- [x] T015 [US1] Update `apps/platform/app/Http/Controllers/ReviewPackDownloadController.php` only as needed to carry the same current pack through the signed download path with delivery metadata intact. No controller update was needed; signed download continuity stayed on the existing pack file and passed validation.
**Checkpoint**: One released review can produce and deliver one stakeholder-ready current bundle without any second export system.
---
## Phase 4: User Story 2 - Show The Executive Story First And The Appendix Second (Priority: P1)
**Goal**: The in-app delivery surfaces and the exported bundle both make the executive narrative the default entrypoint while keeping appendix detail secondary.
**Independent Test**: Open a released review in customer-workspace mode and confirm that the default visible package block and the downloaded current bundle both present executive-first delivery framing without raw internal diagnostics.
### Tests for User Story 2
- [x] T016 [P] [US2] Extend `apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php` and `apps/platform/tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php` to cover only the delivery-readiness wording changes required by the new bundle contract, evidence-basis messaging, and the absence of peer download actions on the workspace list. New wording assertions landed in `CustomerReviewWorkspacePageTest`; existing pack-access tests remained the peer-action guard.
- [x] T017 [P] [US2] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php` and `apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php` to cover executive-first default content, appendix-secondary wording, and hidden raw/internal detail by default. New disclosure assertions landed in `TenantReviewExplanationSurfaceTest`; existing UI-contract tests remained the one-action guard.
- [x] T018 [P] [US2] Extend `apps/platform/tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` to prove the released-review path still centers the customer-safe package summary and dominant download action after the wording changes.
### Implementation for User Story 2
- [x] T019 [US2] Update `apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` and `apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php` only where needed so workspace rows keep delivery readiness informational and `Open review` remains the only dominant row action. No PHP/Blade structure change was needed on the workspace list; localized intro copy now frames executive-ready package status while existing row action tests guard `Open review`.
- [x] T020 [US2] Update `apps/platform/app/Services/TenantReviews/TenantReviewComposer.php`, `apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php`, and `apps/platform/resources/views/filament/infolists/entries/tenant-review-summary.blade.php` only where needed so the released-review detail block explains executive-first delivery, evidence basis, and appendix-secondary meaning without reopening broader customer-safe package semantics already owned by Spec 260. Composer/factory already exposed the required truth; the detail entry now presents entrypoint and appendix wording.
- [x] T021 [US2] Update `apps/platform/lang/en/localization.php` and `apps/platform/lang/de/localization.php` so delivery-readiness, executive-entrypoint, appendix, and non-certification copy stay consistent across workspace, detail, and download paths.
**Checkpoint**: The delivery story is obvious and customer-safe before the bundle is opened, and the workspace/detail surfaces stay calm and non-duplicative.
---
## Phase 5: User Story 3 - Keep Delivery Tenant-Safe, Auditable, And Bounded (Priority: P2)
**Goal**: The sellability improvement remains on the current entitlement, audit, and observability seams.
**Independent Test**: Verify that export and download stay tenant-safe, audit-visible, and free of any second package domain or new delivery workflow state.
### Tests for User Story 3
- [x] T022 [P] [US3] Extend `apps/platform/tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php` and `apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php` to confirm non-members remain `404` and current in-scope download permissions remain authoritative. Existing authorization/download coverage remained valid and passed.
- [x] T023 [P] [US3] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php` and `apps/platform/tests/Feature/TenantReview/TenantReviewUiContractTest.php` to confirm operator export generation remains the only current initiation path and no competing customer-surface generation action appears. Existing UX-contract coverage remained valid and passed.
- [x] T024 [P] [US3] Extend `apps/platform/tests/Feature/TenantReview/TenantReviewAuditLogTest.php` and `apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php` to confirm current audit metadata still records export and download activity without a new audit family. Existing audit/download coverage remained valid and passed.
### Implementation for User Story 3
- [x] T025 [US3] Reuse or minimally extend current audit metadata in `apps/platform/app/Services/Audit/WorkspaceAuditLogger.php` and `apps/platform/app/Support/Audit/AuditActionId.php` only if the current export/download events need explicit delivery-role metadata. No audit-family or action-id change was needed; existing metadata remains authoritative.
- [x] T026 [US3] Review `apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php` and current delivery availability mapping so `available`, `partial`, `unavailable`, `expired`, and `blocked` remain truthful after the new bundle entrypoint is added.
- [x] T027 [US3] Confirm the implementation does not add a new panel, new global search entry, new asset registration, second artifact family, or recurring delivery workflow. If any of those become necessary, stop and split the scope.
**Checkpoint**: Delivery remains attributable, tenant-safe, and bounded to the current export/download seams.
---
## Phase 6: Polish & Cross-Cutting Validation
**Purpose**: Validate the bounded slice and stop without widening scope.
- [x] T028 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/TenantReview/TenantReviewExecutivePackTest.php tests/Feature/TenantReview/TenantReviewExportOperationsUxTest.php tests/Feature/TenantReview/TenantReviewExplanationSurfaceTest.php tests/Feature/TenantReview/TenantReviewUiContractTest.php tests/Feature/TenantReview/TenantReviewAuditLogTest.php tests/Feature/Reviews/CustomerReviewWorkspacePageTest.php tests/Feature/Reviews/CustomerReviewWorkspacePackAccessTest.php tests/Feature/Reviews/CustomerReviewWorkspaceAuthorizationTest.php tests/Feature/ReviewPack/TenantReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php` - passed, 41 tests / 326 assertions.
- [x] T029 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Reviews/CustomerReviewWorkspaceSmokeTest.php` - passed, 1 test / 42 assertions.
- [x] T030 [P] Run `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - passed.
- [x] T031 [P] Review touched code to confirm Filament stays on Livewire v4, provider registration remains unchanged in `apps/platform/bootstrap/providers.php`, no globally searchable resource contract changes, and no new asset strategy appears.
- [x] T032 [P] Review touched code to confirm the bundle stays on the current `ReviewPack` family and the current `ReviewPackGenerate` run path.
- [x] T033 [P] Record the final guardrail, smoke, and scope-boundary outcomes in the active feature close-out without reopening branding, PDF, scheduling, or second-artifact follow-up work. Outcome: no new panel, provider, global search, asset strategy, run type, artifact family, PDF/reporting engine, branding, scheduling, or second delivery workflow; browser smoke passed on the existing Customer Review Workspace handoff.
---
## Dependencies & Execution Order
### Phase Dependencies
- **Phase 1 (Setup)**: no dependencies; start immediately.
- **Phase 2 (Foundational)**: depends on Phase 1 and blocks all user stories.
- **Phase 3 (US1)**: depends on Phase 2 and establishes the current bundle contract.
- **Phase 4 (US2)**: depends on Phase 2 and should land with US1 so the new bundle contract and the in-app delivery language stay aligned.
- **Phase 5 (US3)**: depends on Phase 2 and hardens audit and entitlement behavior after the bundle contract exists.
- **Phase 6 (Polish)**: depends on all desired user stories being complete.
### User Story Dependencies
- **US1 (P1)**: independently testable after Phase 2 and delivers the core stakeholder-ready bundle.
- **US2 (P1)**: independently testable after Phase 2 and should ship with US1 so the delivered bundle and in-app delivery language do not drift apart.
- **US3 (P2)**: independently testable after Phase 2 and hardens the bounded delivery path.
### Within Each User Story
- Write the listed Pest coverage first and make it fail for the intended gap.
- Keep implementation inside the current review-pack, review, download, localization, and audit seams named above.
- Re-run the narrowest relevant validation command after each story checkpoint before moving on.
---
## Implementation Strategy
### Suggested MVP Scope
- MVP = **US1 + US2 together**. The feature is only useful when the current bundle becomes stakeholder-ready and the current in-app delivery surfaces explain it correctly.
### Incremental Delivery
1. Complete Phase 1 and Phase 2.
2. Deliver US1 and US2 together on the current `ReviewPack` family.
3. Add US3 to confirm audit and entitlement continuity.
4. Finish with the focused validation and drift-review tasks in Phase 6.
### Team Strategy
1. Settle the bundle contract first.
2. Parallelize failing tests within each story before runtime edits.
3. Serialize merges around `ViewTenantReview`, `CustomerReviewWorkspace`, and shared localization keys so delivery wording stays coherent.
---
## Deferred Follow-Ups / Non-Goals
- PDF tooling or richer print/export rendering
- recurring delivery or scheduled distribution
- branded or customer-specific delivery variants
- multi-review or multi-tenant delivery batches
- a second artifact family or a standalone auditor-portal surface