diff --git a/.gitignore b/.gitignore
index d4b97fe5..b7918016 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
/bootstrap/ssr
/node_modules
/public/build
+/public/build-qa-opportunities
/public/fonts-manifest.dev.json
/public/hot
/public/storage
diff --git a/app/Console/Commands/ImportDocumentBatch.php b/app/Console/Commands/ImportDocumentBatch.php
index 071ffddd..4f6542dd 100644
--- a/app/Console/Commands/ImportDocumentBatch.php
+++ b/app/Console/Commands/ImportDocumentBatch.php
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\Jobs\ScanDocumentForMalware;
+use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
@@ -56,11 +57,26 @@ class ImportDocumentBatch extends Command
$apply = (bool) $this->option('apply');
$actorId = $this->option('actor');
+ if ($apply) {
+ // CLI attribution is not an authenticated active installation. Rehearsals stay isolated.
+ $target = DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
+ if (! app()->environment('testing') || ! str_ends_with($target->database, '_test') || (int) $target->port !== 55441
+ || config('database.connections.pgsql.host') !== '127.0.0.1' || config('database.connections.pgsql.url')) {
+ $this->error('CLI apply is restricted to isolated QA. Active imports require the authenticated activation mechanism; --actor is attribution only.');
+
+ return self::FAILURE;
+ }
+ }
if ($apply && (! is_numeric($actorId) || ! DB::table('users')->where('id', (int) $actorId)->exists())) {
$this->error('Apply requires --actor=; no author identity will be fabricated.');
return self::FAILURE;
}
+ if ($apply && ! User::findOrFail((int) $actorId)->can('manage-portal')) {
+ $this->error('QA import requires an authorized library manager; no permission is granted by naming an account.');
+
+ return self::FAILURE;
+ }
$disk = Storage::disk('local');
$seenHashes = [];
$seenExternalIds = [];
diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php
index 4e5d96c2..b390d17e 100644
--- a/app/Http/Controllers/DashboardController.php
+++ b/app/Http/Controllers/DashboardController.php
@@ -6,7 +6,9 @@ use App\Models\InterestRequest;
use App\Models\Opportunity;
use App\Models\Sector;
use App\Services\InvestorPath;
+use App\Services\PortalProfileAccess;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Schema;
use Inertia\Inertia;
use Inertia\Response;
@@ -29,12 +31,17 @@ class DashboardController extends Controller
$counts = InterestRequest::query()->selectRaw('status, count(*) as total')
->groupBy('status')->pluck('total', 'status');
+ $drafts = Opportunity::where('status', 'draft');
+ if (Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $drafts = app(PortalProfileAccess::class)->scope($drafts, $request->user());
+ }
return Inertia::render('dashboard', ['summary' => [
+ 'canCreateOpportunity' => app(PortalProfileAccess::class)->legacyWriteAllowed($request->user()),
'requestsByStatus' => collect(['received', 'in_review', 'contacted', 'closed'])
->mapWithKeys(fn ($status) => [$status => (int) ($counts[$status] ?? 0)]),
'publishedOpportunities' => Opportunity::published()->count(),
- 'draftOpportunities' => Opportunity::where('status', 'draft')->count(),
+ 'draftOpportunities' => $drafts->count(),
'activeSectors' => Sector::where('is_active', true)->count(),
'recentRequests' => InterestRequest::orderByDesc('id')->limit(5)
->get(['id', 'reference', 'sector_interest', 'status', 'created_at']),
diff --git a/app/Http/Controllers/InvestmentTerritoryController.php b/app/Http/Controllers/InvestmentTerritoryController.php
index c62511d5..858804ba 100644
--- a/app/Http/Controllers/InvestmentTerritoryController.php
+++ b/app/Http/Controllers/InvestmentTerritoryController.php
@@ -2,11 +2,14 @@
namespace App\Http\Controllers;
+use App\Models\Opportunity;
use App\Services\InvestmentZones;
+use App\Services\PortalProfileAccess;
use App\Services\TerritoryGeometry;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\ValidationException;
class InvestmentTerritoryController extends Controller
@@ -14,9 +17,11 @@ class InvestmentTerritoryController extends Controller
public function geometries(Request $request): JsonResponse
{
$data = $request->validate(['territory_id' => ['required', 'uuid']]);
- $management = $request->is('management/*');
+ $profile = $request->is('minhas-oportunidades/*');
+ $management = $request->is('management/*') || $profile;
if ($management) {
- abort_unless($request->user()?->can('manage-portal'), 403);
+ $access = app(PortalProfileAccess::class);
+ abort_unless($profile ? ($access->grants($request->user()) !== [] || $access->superuser($request->user())) : $request->user()?->can('manage-portal'), 403);
}
return response()->json(app(TerritoryGeometry::class)->context($data['territory_id'], $management));
@@ -29,6 +34,9 @@ class InvestmentTerritoryController extends Controller
$data = $request->validate(['kind' => ['required', 'in:'.implode(',', array_keys(self::TABLES))], 'q' => ['nullable', 'string', 'max:100'], 'page' => ['nullable', 'integer', 'min:1']]);
$column = $data['kind'] === 'opportunities' ? 'title' : 'name';
$query = DB::table(self::TABLES[$data['kind']])->whereNull('deleted_at');
+ if ($data['kind'] === 'opportunities' && Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $query->whereIn('id', app(PortalProfileAccess::class)->scope(Opportunity::query(), $request->user())->select('id'));
+ }
if (! empty($data['q'])) {
$query->whereRaw($column.' ILIKE ?', ['%'.addcslashes($data['q'], '%_\\').'%']);
}
@@ -38,6 +46,10 @@ class InvestmentTerritoryController extends Controller
public function options(Request $request): JsonResponse
{
+ if ($request->is('minhas-oportunidades/*')) {
+ $access = app(PortalProfileAccess::class);
+ abort_unless($access->grants($request->user()) !== [] || $access->superuser($request->user()), 403);
+ }
$data = $request->validate(['type' => ['required', 'in:province,district,admin_post,locality'], 'parent_id' => ['nullable', 'uuid'], 'q' => ['nullable', 'string', 'max:100'], 'page' => ['nullable', 'integer', 'min:1']]);
$query = DB::table('geo_locations')->whereNull('deleted_at')->where('location_type', $data['type'])
->whereIn('data_classification', ['public', 'internal']);
diff --git a/app/Http/Controllers/LandAssistanceController.php b/app/Http/Controllers/LandAssistanceController.php
index 4baba686..1b215fe2 100644
--- a/app/Http/Controllers/LandAssistanceController.php
+++ b/app/Http/Controllers/LandAssistanceController.php
@@ -11,6 +11,7 @@ use App\Models\LandAssistanceCase;
use App\Services\CountryCatalogue;
use App\Services\InterestSubmission;
use App\Services\InvestmentGeography;
+use App\Services\VerifiedDocumentBinary;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -257,7 +258,9 @@ class LandAssistanceController extends Controller
'media_type' => (string) $file->getMimeType(),
'storage_key' => $stored,
'sha256' => hash_file('sha256', Storage::disk('local')->path($stored)),
- // No antivirus engine is configured in this project; fail closed until an operator scans it.
+ 'size_bytes' => $file->getSize(),
+ 'uploaded_by' => $request->user()->id,
+ // The configured scanner releases only the exact original hash after a clean result.
'status' => 'quarantined',
'created_at' => now(),
'updated_at' => now(),
@@ -282,22 +285,20 @@ class LandAssistanceController extends Controller
: back()->with('status', 'Documento privado anexado; a revisão ainda está pendente.');
}
- public function download(Request $request, string $id, string $attachment): BinaryFileResponse
+ public function download(Request $request, string $id, string $attachment): \Illuminate\Http\Response|BinaryFileResponse
{
- $this->owned($request, $id);
+ $case = $this->owned($request, $id);
$document = DB::table('land_assistance_documents as link')->join('documents as document', 'document.id', '=', 'link.document_id')
->where('link.case_id', $id)->where('link.id', $attachment)->where('document.status', 'active')->whereNull('document.deleted_at')
->where('document.malware_scan_status', 'clean')->whereColumn('document.malware_scanned_sha256', 'document.sha256')
- ->first(['document.file_name', 'document.storage_key', 'document.sha256', 'document.malware_scanned_sha256']);
+ ->first(['document.*']);
abort_if($document === null, 404);
- $root = realpath(Storage::disk('local')->path(''));
- $path = realpath(Storage::disk('local')->path($document->storage_key));
- abort_unless($root && $path && str_starts_with($path, $root.DIRECTORY_SEPARATOR) && is_file($path), 404);
- $checksum = hash_file('sha256', $path);
- abort_unless(is_string($checksum) && hash_equals($document->sha256, $checksum)
- && hash_equals($document->sha256, (string) $document->malware_scanned_sha256), 404);
+ $response = app(VerifiedDocumentBinary::class)->respond($document);
+ DB::table('audit_events')->insert(['source_system' => 'land-assistance', 'entity_type' => 'documents', 'entity_id' => $document->id,
+ 'actor_user_id' => $request->user()->id, 'action' => 'document_downloaded', 'data_classification' => 'restricted',
+ 'after_data' => json_encode(['case_id' => $case->id, 'attachment_id' => $attachment], JSON_THROW_ON_ERROR)]);
- return response()->download($path, basename($document->file_name), ['Cache-Control' => 'private, no-store', 'X-Content-Type-Options' => 'nosniff']);
+ return $response;
}
public function print(Request $request, string $id): Response
diff --git a/app/Http/Controllers/OpportunityManagementController.php b/app/Http/Controllers/OpportunityManagementController.php
index 981c58af..1b88eb5c 100644
--- a/app/Http/Controllers/OpportunityManagementController.php
+++ b/app/Http/Controllers/OpportunityManagementController.php
@@ -6,14 +6,20 @@ use App\Domain\Opportunities\Enums\OpportunityStatus;
use App\Models\Opportunity;
use App\Models\Sector;
use App\Services\InvestmentGeography;
+use App\Services\OpportunityCanonicalContract;
use App\Services\OpportunityManagement;
use App\Services\OpportunityManagementInstallation;
use App\Services\OpportunityMaturity;
+use App\Services\OpportunityProfileWorkflow;
use App\Services\OpportunityResources;
+use App\Services\OpportunityWorkflowTasks;
+use App\Services\PortalProfileAccess;
+use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;
@@ -38,16 +44,32 @@ class OpportunityManagementController extends Controller
if (! $service->installed()) {
return app(PortalManagementController::class)->catalog($request, 'opportunities');
}
- $filters = $request->validate(['q' => 'nullable|string|max:150', 'status' => ['nullable', Rule::in([...array_column(OpportunityStatus::cases(), 'value'), 'returned', 'auto_validation_failed', 'technical_review', 'legal_territorial_review', 'approval_pending', 'publication_pending'])], 'sector_id' => ['nullable', 'integer', Rule::exists('sectors', 'id')->whereNull('deleted_at')], 'geography_scope' => ['nullable', Rule::in(['unspecified', 'specific', 'multiple', 'national', 'digital'])], 'category' => ['nullable', Rule::in(OpportunityManagement::CATEGORIES)], 'deleted' => 'nullable|boolean', 'page' => 'nullable|integer|min:1']);
+ $filters = $request->validate(['queue' => 'nullable|in:review,publication,appeal,assigned', 'q' => 'nullable|string|max:150', 'status' => ['nullable', Rule::in([...array_column(OpportunityStatus::cases(), 'value'), 'returned', 'auto_validation_failed', 'technical_review', 'legal_territorial_review', 'approval_pending', 'publication_pending'])], 'sector_id' => ['nullable', 'integer', Rule::exists('sectors', 'id')->whereNull('deleted_at')], 'geography_scope' => ['nullable', Rule::in(['unspecified', 'specific', 'multiple', 'national', 'digital'])], 'category' => ['nullable', Rule::in(OpportunityManagement::CATEGORIES)], 'deleted' => 'nullable|boolean', 'page' => 'nullable|integer|min:1']);
$query = Opportunity::query();
+ $access = app(PortalProfileAccess::class);
+ if (Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $query = $access->scope($query, $request->user());
+ if (str_starts_with($request->path(), 'minhas-oportunidades')) {
+ $query->whereNotNull('owner_user_id');
+ }
+ }
if ($filters['deleted'] ?? false) {
- $query->onlyTrashed();
+ $query->withoutGlobalScope(SoftDeletingScope::class)->whereNotNull('opportunities.deleted_at');
}
if ($filters['q'] ?? null) {
- $query->where(fn ($q) => $q->whereLike('title', '%'.$filters['q'].'%')->orWhereLike('reference', '%'.$filters['q'].'%'));
+ $query->where(function ($q) use ($filters) {
+ $q->whereLike('title', '%'.$filters['q'].'%')->orWhereLike('reference', '%'.$filters['q'].'%');
+ if (Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $q->orWhere(fn ($draft) => $draft->whereNotNull('owner_user_id')->whereRaw("management_draft::jsonb->'canonical'->>'official_title' ILIKE ?", ['%'.$filters['q'].'%']));
+ }
+ });
}
if ($filters['status'] ?? null) {
- $query->where('status', $filters['status']);
+ if (Schema::hasColumn('opportunities', 'workflow_context')) {
+ $query->whereRaw("COALESCE(workflow_context->>'working_state',status)=?", [$filters['status']]);
+ } else {
+ $query->where('status', $filters['status']);
+ }
}
if ($filters['category'] ?? null) {
$query->where('opportunity_category', $filters['category']);
@@ -59,7 +81,32 @@ class OpportunityManagementController extends Controller
$query->where('geography_scope', $filters['geography_scope']);
}
- return Inertia::render('management/opportunities', ['records' => $query->orderByDesc('id')->paginate(20)->withQueryString(), 'filters' => $filters, 'counts' => Opportunity::selectRaw('status,count(*) AS total')->groupBy('status')->pluck('total', 'status'), 'categories' => OpportunityManagement::CATEGORIES, 'geographyReviewCount' => Opportunity::where('geography_scope', 'unspecified')->count(), 'sectors' => Sector::orderBy('name')->get(['id', 'name'])]);
+ if ($filters['queue'] ?? null) {
+ $queue = $filters['queue'];
+ if ($queue === 'review') {
+ $query->whereRaw("COALESCE(workflow_context->>'working_state',status) IN ('submitted','in_review','information_pending')");
+ } elseif ($queue === 'publication') {
+ $query->whereRaw("COALESCE(workflow_context->>'working_state',status)='approved'");
+ } elseif ($queue === 'appeal') {
+ $query->whereRaw("workflow_context->'appeal'->>'pending'='true'");
+ } else {
+ $query->whereExists(fn ($q) => $q->selectRaw('1')->from('tasks')->where('tasks.source_system', 'opportunity-workflow')->where('tasks.assignee_user_id', $request->user()->id)->whereIn('tasks.status', ['open', 'in_progress'])->whereRaw("tasks.external_id LIKE 'portal-opportunity:' || opportunities.id::text || ':%'"));
+ }
+ }
+
+ $base = str_starts_with($request->path(), 'minhas-oportunidades') ? '/minhas-oportunidades' : '/management/opportunities';
+ $stateSql = Schema::hasColumn('opportunities', 'workflow_context') ? "COALESCE(workflow_context->>'working_state',status)" : 'status';
+ $counts = (clone $query)->selectRaw($stateSql.' AS working_status,count(*) AS total')->groupByRaw($stateSql)->pluck('total', 'working_status');
+ $geographyReviewCount = (clone $query)->where('geography_scope', 'unspecified')->count();
+ $records = $query->orderByDesc('id')->paginate(20)->withQueryString();
+ $records->getCollection()->each(function (Opportunity $r) use ($access, $service, $request) {
+ $r->setAttribute('can_edit', $access->canEdit($request->user(), $r));
+ $r->setAttribute('working_status', $access->state($r));
+ $r->setAttribute('publication', $r->publicationPresentation());
+ $r->setAttribute('draft_title', $service->values($r)['canonical']['official_title'] ?? $r->title);
+ });
+
+ return Inertia::render('management/opportunities', ['basePath' => $base, 'canCreate' => $base === '/management/opportunities' ? $access->legacyWriteAllowed($request->user()) : (bool) ($access->navigation($request->user())['contexts'] ?? []), 'records' => $records, 'filters' => $filters, 'counts' => $counts, 'categories' => OpportunityManagement::CATEGORIES, 'geographyReviewCount' => $geographyReviewCount, 'sectors' => Sector::orderBy('name')->get(['id', 'name'])]);
}
public function edit(Request $request, OpportunityManagement $service, ?int $id = null): Response
@@ -68,10 +115,27 @@ class OpportunityManagementController extends Controller
return app(PortalManagementController::class)->edit('opportunities', $id);
}
$record = $id ? Opportunity::withTrashed()->findOrFail($id) : null;
+ $access = app(PortalProfileAccess::class);
+ if (! $record && ! str_starts_with($request->path(), 'minhas-oportunidades')) {
+ abort_unless($access->legacyWriteAllowed($request->user()), 403);
+ }
+ if ($record) {
+ $access->authorize($request->user(), 'view', $record);
+ }
+ Inertia::share(['basePath' => str_starts_with($request->path(), 'minhas-oportunidades') ? '/minhas-oportunidades' : '/management/opportunities',
+ 'canonicalOptions' => ($record?->owner_user_id !== null || str_starts_with($request->path(), 'minhas-oportunidades')) ? app(OpportunityCanonicalContract::class)->options($request->user(), $record) : null,
+ 'workflowState' => $record ? $access->state($record) : null,
+ 'publicationState' => $record?->publicationPresentation(),
+ 'canEditDraft' => $record ? $access->canEdit($request->user(), $record) : false,
+ 'workflowParticipants' => $record && $record->owner_user_id !== null ? app(OpportunityProfileWorkflow::class)->participants($request->user(), $record) : ['validators' => [], 'publishers' => []],
+ 'workflowTasks' => $record && $record->owner_user_id !== null ? app(OpportunityWorkflowTasks::class)->listing($record) : [],
+ 'profileMode' => $record ? $record->owner_user_id !== null : str_starts_with($request->path(), 'minhas-oportunidades'),
+ 'profileActions' => $record && $record->owner_user_id !== null ? app(OpportunityProfileWorkflow::class)->actions($request->user(), $record) : [], 'profileContext' => $record?->workflow_context, 'profileOrganization' => $record?->organization_id]);
$values = $record ? $service->values($record) : [];
+ Inertia::share('publicationPreview', app(OpportunityCanonicalContract::class)->publicProjection($values['canonical'] ?? []));
$classification = $id ? DB::table('audit_events')->where('source_system', 'opportunity-origin-review')->where('after_data->opportunity_id', $id)->orderByDesc('occurred_at')->orderByDesc('id')->value('after_data') : null;
- return Inertia::render('management/opportunity-draft', ['resourcesInstalled' => app(OpportunityResources::class)->installed(), 'record' => $record, 'values' => $values, 'etag' => $record ? $service->etag($record) : null, 'readOnly' => str_ends_with($request->path(), '/view'), 'closedVersion' => $record ? $service->closed($record) : false, 'classification' => $classification ? json_decode($classification, true)['classification'] : 'undetermined', 'sectors' => Sector::where('is_active', true)->orderBy('name')->get(['id', 'name']), 'categories' => OpportunityManagement::CATEGORIES,
+ return Inertia::render('management/opportunity-draft', ['resourcesInstalled' => app(OpportunityResources::class)->installed(), 'record' => $record, 'values' => $values, 'etag' => $record ? $service->etag($record) : null, 'readOnly' => str_ends_with($request->path(), '/view') || ($record && ! $access->canEdit($request->user(), $record)), 'closedVersion' => $record ? $service->closed($record) : false, 'classification' => $classification ? json_decode($classification, true)['classification'] : 'undetermined', 'sectors' => Sector::where('is_active', true)->orderBy('name')->get(['id', 'name']), 'categories' => OpportunityManagement::CATEGORIES,
'maturityCatalogue' => ['version' => OpportunityMaturity::VERSION, 'stages' => OpportunityMaturity::STAGES, 'legacyVersion' => OpportunityMaturity::LEGACY, 'legacyLabels' => OpportunityMaturity::LEGACY_LABELS],
'territoryPath' => app(InvestmentGeography::class)->path($values['primary_territory_id'] ?? null, true),
'history' => $id ? DB::table('audit_events')->where('source_system', 'opportunity-management')->where('after_data->record_id', $id)->orderByDesc('occurred_at')->get(['id', 'action', 'actor_user_id', 'occurred_at']) : []]);
diff --git a/app/Http/Controllers/OpportunityResourceController.php b/app/Http/Controllers/OpportunityResourceController.php
index a13e10d3..ea39ba01 100644
--- a/app/Http/Controllers/OpportunityResourceController.php
+++ b/app/Http/Controllers/OpportunityResourceController.php
@@ -3,21 +3,22 @@
namespace App\Http\Controllers;
use App\Models\Opportunity;
+use App\Services\CountryCatalogue;
use App\Services\InvestmentGeography;
use App\Services\OpportunityImageProcessor;
use App\Services\OpportunityManagement;
use App\Services\OpportunityResourceInstallation;
use App\Services\OpportunityResources;
+use App\Services\PortalProfileAccess;
+use App\Services\VerifiedDocumentBinary;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Inertia\Inertia;
use Inertia\Response;
-use Symfony\Component\HttpFoundation\HeaderUtils;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
class OpportunityResourceController extends Controller
{
@@ -40,9 +41,12 @@ class OpportunityResourceController extends Controller
public function index(int $id, OpportunityResources $service): Response
{
$opportunity = Opportunity::withTrashed()->findOrFail($id);
+ app(PortalProfileAccess::class)->authorize(request()->user(), 'view', $opportunity);
+ Inertia::share(['basePath' => str_starts_with(request()->path(), 'minhas-oportunidades') ? '/minhas-oportunidades' : '/management/opportunities', 'readOnly' => ! app(PortalProfileAccess::class)->canEdit(request()->user(), $opportunity)]);
abort_unless($service->installed(), 503, 'Recursos ainda não instalados; consulte o plano autenticado.');
$resources = [];
Inertia::share('imageProcessingAvailable', app(OpportunityImageProcessor::class)->available());
+ Inertia::share('countries', app(CountryCatalogue::class)->all());
foreach (OpportunityResources::KINDS as $kind) {
$resources[$kind] = $service->listing($id, $kind);
}
@@ -54,7 +58,7 @@ class OpportunityResourceController extends Controller
$image->derivativePreviews = [];
foreach ($image->payload['derivatives'] ?? [] as $derived) {
if (DB::table('documents')->where('id', $derived['document_id'])->where('status', 'active')->where('malware_scan_status', 'clean')->whereColumn('sha256', 'malware_scanned_sha256')->exists()) {
- $image->derivativePreviews[] = [...$derived, 'url' => URL::temporarySignedRoute('management.opportunity-image-preview', now()->addMinutes(10), ['id' => $id, 'resourceId' => $image->id, 'documentId' => $derived['document_id']])];
+ $image->derivativePreviews[] = [...$derived, 'url' => URL::temporarySignedRoute(str_starts_with(request()->path(), 'minhas-oportunidades') ? 'promoter.opportunity-image-preview' : 'management.opportunity-image-preview', now()->addMinutes(10), ['id' => $id, 'resourceId' => $image->id, 'documentId' => $derived['document_id']])];
}
}
}
@@ -87,7 +91,7 @@ class OpportunityResourceController extends Controller
return response()->json(['message' => 'Derivadas WebP geradas sem EXIF original; scan independente e revisão de divulgação pendentes.']);
}
- public function previewImage(int $id, string $resourceId, string $documentId): \Illuminate\Http\Response
+ public function previewImage(int $id, string $resourceId, string $documentId): \Illuminate\Http\Response|BinaryFileResponse
{
$o = Opportunity::findOrFail($id);
abort_if($o->status === 'archived', 404);
@@ -97,26 +101,20 @@ class OpportunityResourceController extends Controller
abort_unless(in_array($documentId, array_column($metadata['derivatives'] ?? [], 'document_id'), true), 404);
$doc = DB::table('documents')->where('id', $documentId)->whereNull('deleted_at')->first();
abort_unless($doc && $doc->status === 'active' && $doc->malware_scan_status === 'clean' && hash_equals(trim($doc->sha256), (string) $doc->malware_scanned_sha256), 423, 'Scan da derivada pendente.');
- $bytes = Crypt::decryptString(Storage::disk('local')->get($doc->storage_key));
- abort_unless(hash_equals(trim($doc->sha256), hash('sha256', $bytes)), 409, 'Integridade divergente.');
- return response($bytes)->header('Content-Type', 'image/webp')->header('X-Content-Type-Options', 'nosniff')->header('Cache-Control', 'private,no-store');
+ return app(VerifiedDocumentBinary::class)->respond($doc, true);
}
- public function download(int $id, string $kind, string $resourceId, OpportunityResources $service): \Illuminate\Http\Response
+ public function download(int $id, string $kind, string $resourceId, OpportunityResources $service): \Illuminate\Http\Response|BinaryFileResponse
{
abort_unless(in_array($kind, ['documents', 'images'], true), 404);
$opportunity = Opportunity::findOrFail($id);
abort_if($opportunity->status === 'archived', 404);
$record = DB::table($service->table($kind).' as r')->join('documents as d', 'd.id', '=', 'r.document_id')->where('r.id', $resourceId)->where('r.opportunity_id', $id)->whereNull('r.deleted_at')->whereNull('d.deleted_at')->first(['d.*']);
- abort_unless($record && $record->status === 'active' && $record->malware_scan_status === 'clean' && hash_equals(trim($record->sha256), (string) $record->malware_scanned_sha256), 423, 'Scan pendente, inconclusivo ou inseguro. O ficheiro permanece em quarentena.');
- $disk = Storage::disk('local');
- $path = $disk->path($record->storage_key);
- abort_unless($disk->exists($record->storage_key), 409, 'Ficheiro indisponível.');
- $bytes = $record->storage_encryption === 'laravel' ? Crypt::decryptString($disk->get($record->storage_key)) : $disk->get($record->storage_key);
- abort_unless(hash_equals(trim($record->sha256), hash('sha256', $bytes)), 409, 'Integridade do ficheiro divergente.');
+ abort_unless($record !== null, 404, 'Recurso indisponível ou excluído logicamente.');
+ abort_unless($record->status === 'active' && $record->malware_scan_status === 'clean' && hash_equals(trim($record->sha256), (string) $record->malware_scanned_sha256), 423, 'Scan pendente, inconclusivo ou inseguro. O ficheiro permanece em quarentena.');
- return response($bytes)->header('Content-Type', $record->media_type)->header('Content-Disposition', HeaderUtils::makeDisposition('attachment', $record->file_name, 'document'))->header('X-Content-Type-Options', 'nosniff')->header('Cache-Control', 'no-store');
+ return app(VerifiedDocumentBinary::class)->respond($record);
}
/** @param array> $resources
diff --git a/app/Http/Controllers/PartnershipExchangeController.php b/app/Http/Controllers/PartnershipExchangeController.php
index 6334789d..96ab3e0d 100644
--- a/app/Http/Controllers/PartnershipExchangeController.php
+++ b/app/Http/Controllers/PartnershipExchangeController.php
@@ -11,6 +11,7 @@ use App\Services\InvestmentRelations;
use App\Services\PartnershipExchange;
use App\Services\PartnershipMatching;
use App\Services\PartnershipSources;
+use App\Services\VerifiedDocumentBinary;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -317,7 +318,7 @@ class PartnershipExchangeController extends Controller
abort_unless($locked !== null && ! in_array($locked->status, ['closed', 'cancelled'], true), 409);
DB::table('documents')->insert(['id' => $documentId, 'source_system' => 'partnership-exchange', 'data_classification' => 'restricted',
'file_name' => basename($file->getClientOriginalName()), 'media_type' => $file->getMimeType(), 'storage_key' => $stored,
- 'sha256' => hash_file('sha256', Storage::disk('local')->path($stored)), 'status' => 'quarantined']);
+ 'sha256' => hash_file('sha256', Storage::disk('local')->path($stored)), 'status' => 'quarantined', 'size_bytes' => $file->getSize(), 'uploaded_by' => $request->user()->id]);
DB::table('partnership_documents')->insert(['room_id' => $id, 'document_id' => $documentId, 'owner_id' => $request->user()->id, 'shared' => $data['shared']]);
app(PartnershipExchange::class)->event($context['partnership'], $request->user(), 'partnership.document_added.v1', ['room_id' => $id, 'document_id' => $documentId, 'shared' => $data['shared']], 'Documento privado anexado');
});
@@ -330,21 +331,17 @@ class PartnershipExchangeController extends Controller
return $request->expectsJson() ? response()->json(['uploaded' => true]) : back()->with('success', 'Documento privado guardado; análise antimalware pendente.');
}
- public function download(Request $request, int $id, int $attachment): BinaryFileResponse
+ public function download(Request $request, int $id, int $attachment): \Illuminate\Http\Response|BinaryFileResponse
{
$context = app(PartnershipExchange::class)->room($request->user(), $id);
$document = DB::table('partnership_documents as link')->join('documents as d', 'd.id', '=', 'link.document_id')->where('link.room_id', $id)->where('link.id', $attachment)
->where(fn ($q) => $q->where('link.shared', true)->orWhere('link.owner_id', $request->user()->id))->where('d.status', 'active')->whereNull('d.deleted_at')
- ->where('d.malware_scan_status', 'clean')->whereColumn('d.malware_scanned_sha256', 'd.sha256')->first(['d.storage_key', 'd.file_name', 'd.sha256']);
+ ->where('d.malware_scan_status', 'clean')->whereColumn('d.malware_scanned_sha256', 'd.sha256')->first(['d.*']);
abort_unless($document !== null, 404);
- $root = realpath(Storage::disk('local')->path(''));
- $path = realpath(Storage::disk('local')->path($document->storage_key));
- abort_unless($root && $path && str_starts_with($path, $root.DIRECTORY_SEPARATOR) && is_file($path), 404);
- $checksum = hash_file('sha256', $path);
- abort_unless(is_string($checksum) && hash_equals($document->sha256, $checksum), 404);
+ $response = app(VerifiedDocumentBinary::class)->respond($document);
app(PartnershipExchange::class)->event($context['partnership'], $request->user(), 'partnership.document_accessed.v1', ['room_id' => $id, 'attachment_id' => $attachment], 'Documento consultado');
- return response()->download($path, basename($document->file_name), ['Cache-Control' => 'private, no-store', 'X-Content-Type-Options' => 'nosniff']);
+ return $response;
}
public function share(Request $request, int $id, int $attachment): RedirectResponse|JsonResponse
diff --git a/app/Http/Controllers/PortalManagementController.php b/app/Http/Controllers/PortalManagementController.php
index e3182eaf..551fff4f 100644
--- a/app/Http/Controllers/PortalManagementController.php
+++ b/app/Http/Controllers/PortalManagementController.php
@@ -230,6 +230,9 @@ class PortalManagementController extends Controller
]);
$query = $model::query();
if ($resource === 'opportunities') {
+ if (Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $query = app(\App\Services\PortalProfileAccess::class)->scope(Opportunity::query(), $request->user());
+ }
$query->with('primaryTerritory:id,name,location_type,source_system,source_code');
if (isset($filters['geography_scope'])) {
$query->where('geography_scope', $filters['geography_scope']);
@@ -263,7 +266,7 @@ class PortalManagementController extends Controller
'filters' => $filters,
'sectors' => $resource === 'opportunities' ? Sector::orderBy('name')->get(['id', 'name']) : [],
'geographyReviewCount' => $resource === 'opportunities'
- ? Opportunity::where('geography_scope', 'unspecified')->count()
+ ? (clone $query)->where('geography_scope', 'unspecified')->count()
: 0,
]);
}
diff --git a/app/Http/Controllers/PortalProfileController.php b/app/Http/Controllers/PortalProfileController.php
new file mode 100644
index 00000000..9708eab2
--- /dev/null
+++ b/app/Http/Controllers/PortalProfileController.php
@@ -0,0 +1,161 @@
+ DB::table('portal_profile_requests')->where('user_id', $request->user()->id)->latest()->get(),
+ 'types' => OpportunityManagement::CATEGORIES,
+ 'organizations' => DB::table('memberships as m')->join('organizations as o', 'o.id', '=', 'm.organization_id')->where('m.user_id', $request->user()->id)
+ ->whereNull('m.deleted_at')->whereNull('o.deleted_at')->whereIn('m.role', ['admin', 'manager', 'officer'])->get(['o.id', 'o.name']),
+ 'documents' => DB::table('documents')->where('uploaded_by', $request->user()->id)->whereNull('deleted_at')->where('status', 'active')->where('malware_scan_status', 'clean')
+ ->whereColumn('sha256', 'malware_scanned_sha256')->get(['id', 'file_name']), 'grants' => $access->grants($request->user(), 'promoter')]);
+ }
+
+ public function requestProfile(Request $request, PortalProfileAdministration $service): JsonResponse
+ {
+ return response()->json(['id' => $service->request($request->user(), $request->all()), 'message' => 'Pedido recebido; perfil ainda não ativado.'], 201);
+ }
+
+ public function requestStatus(Request $request, string $id): JsonResponse
+ {
+ $row = DB::table('portal_profile_requests')->where('id', $id)->where('user_id', $request->user()->id)->first();
+ abort_unless($row !== null, 403);
+
+ return response()->json($row);
+ }
+
+ public function administration(Request $request, PortalProfileAdministration $service): Response
+ {
+ $service->administrative($request->user());
+
+ return Inertia::render('profiles/administration', ['requests' => DB::table('portal_profile_requests')->latest()->get(),
+ 'assignments' => DB::table('portal_role_assignments')->get(), 'pair' => DB::table('portal_superuser_pair')->first(),
+ 'actorId' => $request->user()->id, 'types' => OpportunityManagement::CATEGORIES,
+ 'organizations' => DB::table('organizations')->whereNull('deleted_at')->get(['id', 'name']),
+ 'securityRequests' => DB::table('portal_security_approvals')->latest()->limit(30)->get(),
+ 'securityAlerts' => DB::table('audit_events')->where('source_system', 'portal-profiles-v1')->whereIn('action', ['superuser_pair_initialized', 'superuser_replaced', 'role_revoked'])->latest('occurred_at')->limit(20)->get(['id', 'action', 'actor_user_id', 'occurred_at'])]);
+ }
+
+ public function decide(Request $request, string $id, PortalProfileAdministration $service): JsonResponse
+ {
+ $service->decide($request->user(), $id, $request->all());
+
+ return response()->json(['message' => 'Decisão registada; somente os tipos aprovados ficam autorizados.']);
+ }
+
+ public function audit(Request $request, PortalProfileAccess $access): Response|JsonResponse
+ {
+ abort_unless($access->has($request->user(), 'auditor') || ($access->superuser($request->user()) && $access->mfa($request->user())), 403);
+ $filters = $request->validate(['actor_id' => 'nullable|integer|min:1', 'action' => 'nullable|string|max:100', 'record_id' => 'nullable|integer|min:1', 'from' => 'nullable|date', 'until' => 'nullable|date|after_or_equal:from', 'format' => 'nullable|in:json']);
+ $query = DB::table('audit_events')->when($filters['actor_id'] ?? null, fn ($q, $v) => $q->where('actor_user_id', $v))
+ ->when($filters['action'] ?? null, fn ($q, $v) => $q->where('action', $v))
+ ->when($filters['record_id'] ?? null, fn ($q, $v) => $q->where('after_data->record_id', $v))
+ ->when($filters['from'] ?? null, fn ($q, $v) => $q->where('occurred_at', '>=', $v))
+ ->when($filters['until'] ?? null, fn ($q, $v) => $q->where('occurred_at', '<=', $v));
+ // Minimized metadata: never decrypt private snapshots or export authentication bodies.
+ $query->select(['id', 'source_system', 'action', 'actor_user_id', 'entity_type', 'occurred_at', 'correlation_id']);
+ if (($filters['format'] ?? null) === 'json') {
+ $records = $query->orderByDesc('occurred_at')->limit(1000)->get();
+ $access->audit($request->user(), 'audit_metadata_exported', ['filters' => $filters, 'count' => $records->count()]);
+
+ return response()->json(['filters' => $filters, 'records' => $records, 'limit' => 1000])->header('Content-Disposition', 'attachment; filename="audit-metadata.json"')->header('Cache-Control', 'private, no-store');
+ }
+ $records = $query->orderByDesc('occurred_at')->paginate(30)->withQueryString();
+ $access->audit($request->user(), 'audit_metadata_read', ['filters' => $filters, 'count' => $records->count()]);
+
+ return Inertia::render('profiles/audit', ['records' => $records, 'filters' => $filters]);
+ }
+
+ public function grant(Request $request, PortalProfileAdministration $service): JsonResponse
+ {
+ return response()->json(['id' => $service->grant($request->user(), $request->all())], 201);
+ }
+
+ public function requestDocument(Request $request, string $id, string $documentId, PortalProfileAdministration $service): \Illuminate\Http\Response|BinaryFileResponse
+ {
+ $service->administrative($request->user());
+ $row = DB::table('portal_profile_requests')->where('id', $id)->first();
+ abort_unless($row && in_array($documentId, json_decode($row->document_ids, true), true), 404);
+ $document = DB::table('documents')->where('id', $documentId)->first();
+ abort_unless($document !== null, 404);
+
+ return app(VerifiedDocumentBinary::class)->respond($document, true);
+ }
+
+ public function revoke(Request $request, string $id, PortalProfileAdministration $service): JsonResponse
+ {
+ $service->revoke($request->user(), $id, (string) $request->input('reason'));
+
+ return response()->json(['message' => 'Papel revogado; sessões e tokens anteriores invalidados.']);
+ }
+
+ public function opportunities(Request $request, PortalProfileAccess $access): Response
+ {
+ abort_unless($access->grants($request->user()) !== [] || $access->superuser($request->user()), 403);
+
+ return app(OpportunityManagementController::class)->index($request, app(OpportunityManagement::class));
+ }
+
+ public function edit(Request $request, PortalProfileAccess $access, ?int $id = null): Response
+ {
+ if ($id) {
+ $access->authorize($request->user(), str_ends_with($request->path(), '/view') ? 'view' : 'edit', Opportunity::withTrashed()->findOrFail($id));
+ } else {
+ abort_unless($access->navigation($request->user())['contexts'] ?? [], 403);
+ }
+
+ return app(OpportunityManagementController::class)->edit($request, app(OpportunityManagement::class), $id);
+ }
+
+ public function workflow(Request $request, int $id, OpportunityProfileWorkflow $service): JsonResponse
+ {
+ $record = $service->transition($request->user(), $id, $request->all());
+
+ return response()->json(['id' => $id, 'status' => app(PortalProfileAccess::class)->state($record), 'publication_status' => $record->status, 'etag' => app(OpportunityManagement::class)->etag($record), 'message' => 'Ação interna registada; não representa decisão externa.']);
+ }
+
+ public function replacement(Request $request, PortalSuperusers $service): JsonResponse
+ {
+ $data = $request->validate(['old_user_id' => 'required|integer', 'new_user_id' => 'required|integer', 'reason' => 'required|string|min:20|max:1000']);
+
+ return response()->json(['id' => $service->requestReplacement($request->user(), $data['old_user_id'], $data['new_user_id'], $data['reason'])], 201);
+ }
+
+ public function approveSecurity(Request $request, string $id, PortalSuperusers $service): JsonResponse
+ {
+ $service->approve($request->user(), $id);
+
+ return response()->json(['message' => 'Aprovação independente registada.']);
+ }
+
+ public function replace(Request $request, string $id, PortalSuperusers $service): JsonResponse
+ {
+ $service->applyReplacement($request->user(), $id);
+
+ return response()->json(['message' => 'Titular substituído atomicamente; continuam dois titulares.']);
+ }
+
+ public function elevation(Request $request, PortalSuperusers $service): JsonResponse
+ {
+ $data = $request->validate(['action' => 'required|string', 'record_id' => 'nullable|integer|exists:opportunities,id', 'reason' => 'required|string|min:20|max:1000']);
+
+ return response()->json(['id' => $service->requestElevation($request->user(), $data['action'], $data['record_id'] ?? null, $data['reason'])], 201);
+ }
+}
diff --git a/app/Http/Controllers/PortalProfileInstallationController.php b/app/Http/Controllers/PortalProfileInstallationController.php
new file mode 100644
index 00000000..84b381db
--- /dev/null
+++ b/app/Http/Controllers/PortalProfileInstallationController.php
@@ -0,0 +1,29 @@
+preview($request->user());
+
+ return $request->expectsJson() ? response()->json($plan) : Inertia::render('profiles/installation', $plan);
+ }
+
+ public function apply(Request $request, PortalProfileInstallation $installation): JsonResponse
+ {
+ return response()->json($installation->apply($request->user(), $request->all()));
+ }
+
+ public function bootstrap(Request $request, PortalProfileInstallation $installation): JsonResponse
+ {
+ return response()->json($installation->bootstrap($request->user(), $request->all()));
+ }
+}
diff --git a/app/Http/Middleware/AuditProfileDecision.php b/app/Http/Middleware/AuditProfileDecision.php
new file mode 100644
index 00000000..d3f746cc
--- /dev/null
+++ b/app/Http/Middleware/AuditProfileDecision.php
@@ -0,0 +1,38 @@
+user() || ! $access->available() || ! preg_match('#^(perfil/|perfis/|minhas-oportunidades)#', $request->path())) {
+ return $next($request);
+ }
+ try {
+ $response = $next($request);
+ } catch (\Throwable $error) {
+ $status = $error instanceof HttpExceptionInterface ? $error->getStatusCode() : ($error instanceof ValidationException ? 422 : 500);
+ $this->record($request, $access, $status);
+ throw $error;
+ }
+ if ($response->getStatusCode() >= 400) {
+ $this->record($request, $access, $response->getStatusCode());
+ }
+
+ return $response;
+ }
+
+ private function record(Request $request, PortalProfileAccess $access, int $status): void
+ {
+ $access->audit($request->user(), 'request_denied', ['method' => $request->method(), 'path' => $request->path(), 'status' => $status]);
+ }
+}
diff --git a/app/Http/Middleware/EnsurePortalProfiles.php b/app/Http/Middleware/EnsurePortalProfiles.php
new file mode 100644
index 00000000..8f6f9d2b
--- /dev/null
+++ b/app/Http/Middleware/EnsurePortalProfiles.php
@@ -0,0 +1,19 @@
+available(), 503, 'Autorização por perfis ainda não instalada.');
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php
index 45920145..fe276580 100644
--- a/app/Http/Middleware/HandleInertiaRequests.php
+++ b/app/Http/Middleware/HandleInertiaRequests.php
@@ -3,6 +3,8 @@
namespace App\Http\Middleware;
use App\Services\InvestorPath;
+use App\Services\OpportunityManagement;
+use App\Services\PortalProfileAccess;
use Illuminate\Http\Request;
use Inertia\Middleware;
@@ -24,6 +26,14 @@ class HandleInertiaRequests extends Middleware
*/
public function version(Request $request): ?string
{
+ if (app()->environment('testing') && config('portal.qa_build_directory')) {
+ $manifest = public_path(config('portal.qa_build_directory').'/manifest.json');
+
+ $version = is_file($manifest) ? hash_file('xxh128', $manifest) : false;
+
+ return $version === false ? null : $version;
+ }
+
return parent::version($request);
}
@@ -39,11 +49,18 @@ class HandleInertiaRequests extends Middleware
return [
...parent::share($request),
'name' => config('app.name'),
+ 'profileAccess' => app(PortalProfileAccess::class)->navigation($request->user()),
'portalOperator' => config('portal.operator_name'),
'educationEnabled' => (bool) config('education.enabled', false),
'aiEnabled' => (bool) config('investmoz_ai.enabled', false),
'existingBusinessEnabled' => (bool) config('existing-business.enabled', false),
'investorPathEnabled' => app(InvestorPath::class)->available(),
+ 'opportunityManagement' => config('portal.opportunity_dashboard_access_enabled') && $request->user() && app(PortalProfileAccess::class)->legacyWriteAllowed($request->user()) ? [
+ 'installed' => app(OpportunityManagement::class)->installed(),
+ 'manage' => ['label' => 'Gestão de Oportunidades', 'href' => '/management/opportunities'],
+ 'create' => ['label' => 'Nova oportunidade', 'href' => '/management/opportunities/create'],
+ 'installationHref' => '/management/opportunity-management-install',
+ ] : null,
'flash' => ['success' => fn () => $request->session()->get('success'), 'warning' => fn () => $request->session()->get('warning')],
'auth' => [
'user' => $request->user(),
diff --git a/app/Http/Middleware/PortalProfileSession.php b/app/Http/Middleware/PortalProfileSession.php
new file mode 100644
index 00000000..17301ea4
--- /dev/null
+++ b/app/Http/Middleware/PortalProfileSession.php
@@ -0,0 +1,40 @@
+available();
+ if ($request->user() && config('portal.profile_access_enabled') && ! $available) {
+ $recovery = $request->is('management/profile-install', 'management/profile-install/bootstrap')
+ || ($request->is('logout') && $request->isMethod('POST'));
+ abort_if(! in_array($request->method(), ['GET', 'HEAD', 'OPTIONS'], true) && ! $recovery, 503,
+ 'Autorizações indisponíveis: recuperar a consistência dos perfis antes de gravar. Pode terminar a sessão ou consultar o instalador.');
+ }
+ if ($request->user() && $available) {
+ $revision = (int) DB::table('users')->where('id', $request->user()->id)->value('portal_access_revision');
+ $bound = $request->session()->get('portal.access_revision');
+ if (($bound === null && $revision > 0) || ($bound !== null && (int) $bound !== $revision)) {
+ Auth::guard('web')->logout();
+ $request->session()->invalidate();
+ $request->session()->regenerateToken();
+
+ return $request->expectsJson() ? response()->json(['message' => 'A autorização foi alterada. Inicie uma nova sessão.'], 401)
+ : redirect('/login')->withErrors(['email' => 'A autorização foi alterada. Inicie uma nova sessão.']);
+ }
+ $request->session()->put('portal.access_revision', $revision);
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/ProtectPrivilegedIdentity.php b/app/Http/Middleware/ProtectPrivilegedIdentity.php
new file mode 100644
index 00000000..a9874d50
--- /dev/null
+++ b/app/Http/Middleware/ProtectPrivilegedIdentity.php
@@ -0,0 +1,41 @@
+user();
+ $access = app(PortalProfileAccess::class);
+ if (! $actor || ! $access->available()) {
+ return $next($request);
+ }
+ if (! in_array($request->method(), ['GET', 'HEAD', 'OPTIONS'], true) && $access->has($actor, 'auditor')
+ && $request->is('management/*', 'api/v1/investment/admin/*', 'api/v2/investment/admin/*')) {
+ $access->audit($actor, 'auditor_administrative_write_denied', ['method' => $request->method(), 'path' => $request->path()]);
+ abort(403, 'Auditor só permite leitura administrativa, mesmo com outro papel ou permissão legada.');
+ }
+ $mandatoryMfa = $access->superuser($actor) || $access->has($actor, 'validator') || $access->has($actor, 'publisher');
+ $denied = $request->isMethod('DELETE') && $request->is('user/two-factor-authentication') && $mandatoryMfa;
+ $denied = $denied || ($access->superuser($actor) && $request->is('settings/profile') && $request->isMethod('PATCH')
+ && $request->has('email') && $request->input('email') !== $actor->email);
+ if ($request->isMethod('DELETE') && $request->is('settings/profile')) {
+ $denied = $denied || $access->superuser($actor)
+ || DB::table('portal_role_assignments')->where('user_id', $actor->id)->orWhere('approved_by', $actor->id)->exists()
+ || DB::table('portal_profile_requests')->where('user_id', $actor->id)->orWhere('decided_by', $actor->id)->exists();
+ }
+ if ($denied) {
+ $access->audit($actor, 'privileged_identity_change_denied', ['method' => $request->method(), 'path' => $request->path()]);
+ abort(403, 'Esta alteração removeria MFA obrigatório, um titular ou histórico de autorização. Use revogação ou substituição controlada; não desative MFA para recuperar acesso.');
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/ProtectProfileOpportunity.php b/app/Http/Middleware/ProtectProfileOpportunity.php
new file mode 100644
index 00000000..8a59d6b1
--- /dev/null
+++ b/app/Http/Middleware/ProtectProfileOpportunity.php
@@ -0,0 +1,40 @@
+path(), $match)) {
+ $id = (int) $match[1];
+ } elseif ($request->is('management/opportunity-origin/preview', 'management/opportunity-origin/apply')) {
+ $id = filter_var($request->input('id'), FILTER_VALIDATE_INT) ?: null;
+ } elseif ($request->is('api/v2/investment/admin/zones/*/links')) {
+ $id = filter_var($request->input('opportunity_id'), FILTER_VALIDATE_INT) ?: null;
+ }
+ if ($request->user() && $id !== null && Schema::hasColumn('opportunities', 'owner_user_id')) {
+ $record = Opportunity::withTrashed()->find($id);
+ if ($record && $record->owner_user_id === null && ! $request->isMethod('GET')) {
+ abort_unless(app(PortalProfileAccess::class)->legacyWriteAllowed($request->user()), 403, 'O papel v1 não contorna os controlos através de um registo legado.');
+ }
+ if ($record && ($record->owner_user_id !== null || str_starts_with($request->path(), 'minhas-oportunidades'))) {
+ abort_if($record->owner_user_id === null && str_starts_with($request->path(), 'minhas-oportunidades'), 403, 'Registo legado não convertido para a política v1.');
+ $access = app(PortalProfileAccess::class);
+ $access->authorize($request->user(), $request->isMethod('GET') || str_ends_with($request->path(), '/workflow') || str_ends_with($request->path(), '/preview') ? 'view' : 'edit', $record);
+ abort_if($request->is('management/opportunity-origin/apply'), 403, 'O cadastro privado v1 não usa a classificação editorial dos exemplos legados.');
+ abort_if($request->isMethod('POST') && str_ends_with($request->path(), '/lifecycle') && ! str_contains($request->path(), '/resources/'), 403, 'Use o workflow com decisões segregadas; o perfil não concede exclusão.');
+ }
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Models/Opportunity.php b/app/Models/Opportunity.php
index 828bcc77..fefeb605 100644
--- a/app/Models/Opportunity.php
+++ b/app/Models/Opportunity.php
@@ -7,8 +7,12 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Support\Facades\Schema;
/**
+ * @property int|null $owner_user_id
+ * @property string|null $organization_id
+ * @property array|null $workflow_context
* @property string|null $primary_territory_id
* @property int $territory_version
* @property int $management_version
@@ -23,7 +27,7 @@ class Opportunity extends Model
{
use SoftDeletes;
- protected $hidden = ['management_draft', 'management_creation_key', 'management_version', 'first_submitted_at', 'management_closed_once'];
+ protected $hidden = ['management_draft', 'management_creation_key', 'management_version', 'first_submitted_at', 'management_closed_once', 'owner_user_id', 'organization_id', 'workflow_context'];
protected $fillable = [
'sector_id', 'reference', 'title', 'slug', 'summary', 'description',
@@ -37,6 +41,7 @@ class Opportunity extends Model
];
protected $casts = [
+ 'workflow_context' => 'array',
'is_featured' => 'boolean',
'territory_version' => 'integer',
'published_at' => 'datetime',
@@ -44,6 +49,20 @@ class Opportunity extends Model
'estimated_investment_amount' => 'decimal:2',
];
+ /** @return array{scope:string,label:string,public_catalog:bool} */
+ public function publicationPresentation(): array
+ {
+ $public = $this->exists && self::query()->whereKey($this->id)->published()->exists();
+ $visible = ! $this->trashed() && $this->status === 'published' && $this->published_at !== null && $this->published_at->lte(now());
+ $scope = $public ? 'public' : ($visible && $this->owner_user_id !== null ? 'restricted' : 'unpublished');
+
+ return ['scope' => $scope, 'public_catalog' => $public, 'label' => match ($scope) {
+ 'public' => 'Publicada no catálogo público',
+ 'restricted' => 'Disponibilizada com acesso restrito — perfis e organização autorizados',
+ default => 'Sem versão disponibilizada; aprovação interna é uma etapa distinta',
+ }];
+ }
+
/** @return BelongsTo */
public function sector(): BelongsTo
{
@@ -67,6 +86,10 @@ class Opportunity extends Model
*/
public function scopePublished(Builder $query): Builder
{
+ if (Schema::hasColumn('opportunities', 'workflow_context')) {
+ $query->where(fn ($q) => $q->whereNull('owner_user_id')->orWhere('workflow_context->publication->visibility', 'public'));
+ }
+
return $query->where('status', 'published')->whereNotNull('published_at')->where('published_at', '<=', now())
->whereRaw("COALESCE((SELECT origin.after_data->>'classification' FROM audit_events origin WHERE origin.source_system='opportunity-origin-review' AND origin.after_data->>'opportunity_id'=opportunities.id::text ORDER BY origin.occurred_at DESC,origin.id DESC LIMIT 1),'undetermined') <> 'example'");
}
diff --git a/app/Models/User.php b/app/Models/User.php
index 19878117..fe1fd722 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -19,6 +19,7 @@ use Laravel\Fortify\TwoFactorAuthenticatable;
* @property string $name
* @property string $email
* @property Carbon|null $email_verified_at
+ * @property int $portal_access_revision
* @property string $password
* @property string|null $two_factor_secret
* @property string|null $two_factor_recovery_codes
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index ab0e352c..e18bc487 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -9,16 +9,20 @@ use App\Services\Malware\ClamDScanner;
use App\Services\Malware\MalwareScanner;
use App\Services\Mne\BusinessRepository;
use App\Services\Mne\CompatibleBusinessRepository;
+use App\Services\PortalProfileAccess;
use Carbon\CarbonImmutable;
+use Illuminate\Auth\Events\Login;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password;
+use Laravel\Fortify\Events\ValidTwoFactorAuthenticationCodeProvided;
class AppServiceProvider extends ServiceProvider
{
@@ -39,6 +43,17 @@ class AppServiceProvider extends ServiceProvider
{
$this->configureDefaults();
+ Event::listen(ValidTwoFactorAuthenticationCodeProvided::class, function ($event): void {
+ if (app(PortalProfileAccess::class)->available()) {
+ session()->put(['portal.mfa_actor' => $event->user->id, 'portal.mfa_at' => time()]);
+ }
+ });
+ Event::listen(Login::class, function ($event): void {
+ if (app(PortalProfileAccess::class)->available()) {
+ session()->put('portal.access_revision', (int) DB::table('users')->where('id', $event->user->id)->value('portal_access_revision'));
+ }
+ });
+
Gate::define('manage-portal', fn (User $user) => $user->hasVerifiedEmail()
&& in_array(strtolower($user->email), config('portal.managers', []), true));
diff --git a/app/Services/OpportunityCanonicalContract.php b/app/Services/OpportunityCanonicalContract.php
new file mode 100644
index 00000000..b32e8635
--- /dev/null
+++ b/app/Services/OpportunityCanonicalContract.php
@@ -0,0 +1,437 @@
+ */
+ public function schema(bool $draft = false): array
+ {
+ $bytes = file_get_contents(resource_path('data/investmoz-opportunity-modular.schema.json'));
+ if ($bytes === false) {
+ throw new \RuntimeException('Opportunity schema unavailable.');
+ }
+ $schema = json_decode($bytes, true, 512, JSON_THROW_ON_ERROR);
+ // The original conditions were omitted from the extracted Create/Patch definitions.
+ foreach (['opportunity', 'realEstate', 'landRights', 'businessTransaction'] as $name) {
+ $schema['$defs'][$name.'Create']['allOf'] = $schema['$defs'][$name]['allOf'] ?? [];
+ }
+ $schema = app(OpportunityCategoryFields::class)->enrich($schema);
+ $schema = $this->writeSchema($schema, $draft);
+ $properties = &$schema['$defs']['opportunityCreate']['properties'];
+ unset($properties['mutation_context']); // Actor, audit reason and revision are server-owned.
+ $properties['sector_id'] = ['type' => 'integer', 'minimum' => 1];
+ $properties['promoter_id'] = ['type' => ['string', 'integer']];
+ // References point to the existing collections; their metadata is recovered on the server.
+ foreach (['locations', 'documents', 'images'] as $field) {
+ $properties[$field]['items'] = ['type' => 'string', 'format' => 'uuid'];
+ }
+ $properties['evidences'] = ['type' => 'array', 'items' => ['$ref' => '#/$defs/evidenceCreate']];
+ if (! $draft) {
+ $properties['evidences']['minItems'] = 1;
+ }
+ $properties['evidences']['items'] = ['type' => 'object', 'additionalProperties' => false,
+ 'properties' => ['title' => ['type' => 'string'], 'evidence_type' => ['type' => 'string'],
+ 'document_id' => ['type' => 'string', 'format' => 'uuid'], 'description' => ['type' => 'string']],
+ ...($draft ? [] : ['required' => ['title', 'evidence_type', 'document_id']])];
+ $schema['$ref'] = '#/$defs/opportunityCreate';
+ $schema['$id'] = 'urn:investmoz:'.self::VERSION.($draft ? ':draft' : ':submit');
+
+ return $schema;
+ }
+
+ /**
+ * @param array $node
+ * @return array
+ */
+ private function writeSchema(array $node, bool $draft): array
+ {
+ if (isset($node['$ref']) && preg_match('~^#/\$defs/(.+)$~', $node['$ref'], $match)) {
+ // Collections in the normative Create still referenced response definitions.
+ $defs = ['product', 'asset', 'input', 'market', 'impact', 'moneyItem', 'milestone', 'license', 'risk', 'relation', 'employment', 'environmentalSocial', 'localizedPublication', 'realEstate', 'landRights', 'businessTransaction', 'parcel', 'improvement', 'community'];
+ if (in_array($match[1], $defs, true)) {
+ $node['$ref'] .= 'Create';
+ }
+ }
+ if ($draft) {
+ unset($node['required'], $node['minItems'], $node['minProperties'], $node['contains'], $node['allOf']);
+ if (isset($node['type'])) {
+ $node['type'] = array_values(array_unique([...(array) $node['type'], 'null']));
+ }
+ if (isset($node['enum']) && ! in_array(null, $node['enum'], true)) {
+ $node['enum'][] = null;
+ }
+ if (isset($node['minLength'])) {
+ $node['minLength'] = 0;
+ }
+ if (($node['const'] ?? null) === true) {
+ unset($node['const']);
+ $node['type'] = 'boolean';
+ }
+ }
+ foreach ($node as $key => $value) {
+ if (is_array($value)) {
+ if (in_array($key, ['properties', '$defs'], true)) {
+ foreach ($value as $name => $child) {
+ $value[$name] = $this->writeSchema($child, $draft);
+ }
+ $node[$key] = $value;
+ } elseif (in_array($key, ['items', 'if', 'then', 'else'], true)) {
+ $node[$key] = $this->writeSchema($value, $draft);
+ } elseif (in_array($key, ['allOf', 'oneOf', 'anyOf'], true)) {
+ $node[$key] = array_map(fn ($child) => $this->writeSchema($child, $draft), $value);
+ }
+ }
+ }
+
+ return $node;
+ }
+
+ /**
+ * @param array $payload
+ * @return array
+ */
+ public function draft(array $payload): array
+ {
+ abort_unless(config('portal.opportunity_specialized_drafts_enabled'), 422, 'Contrato especializado indisponível.');
+ $this->validateSchema($payload, true);
+
+ return $payload;
+ }
+
+ /** @param array $payload */
+ private function validateSchema(array $payload, bool $draft): void
+ {
+ $schema = $this->schema($draft);
+ $validator = new CompliantValidator(null, 100, false);
+ $data = $this->schemaData($payload, $schema['$defs']['opportunityCreate'], $schema['$defs']);
+ $result = $validator->validate($data, json_decode(json_encode($schema, JSON_THROW_ON_ERROR)));
+ if ($error = $result->error()) {
+ $errors = [];
+ foreach ((new ErrorFormatter)->format($error) as $path => $messages) {
+ $errors['canonical'.str_replace('/', '.', $path)] = $messages;
+ }
+ $required = function (ValidationError $node) use (&$required, &$errors): void {
+ if ($node->keyword() === 'required') {
+ $prefix = 'canonical.'.implode('.', $node->data()->fullPath());
+ foreach ($node->args()['missing'] ?? [] as $field) {
+ $errors[rtrim($prefix, '.').'.'.$field] = ['Preencha este campo antes de submeter.'];
+ }
+ }
+ foreach ($node->subErrors() as $child) {
+ $required($child);
+ }
+ };
+ $required($error);
+ throw ValidationException::withMessages($errors);
+ }
+ }
+
+ /** @param array $node
+ * @param array $defs
+ */
+ private function schemaData(mixed $value, array $node, array $defs): mixed
+ {
+ if (isset($node['$ref'])) {
+ $name = basename($node['$ref']);
+ $node = $defs[$name] ?? $node;
+ }
+ if (! is_array($value)) {
+ return $value;
+ }
+ if (in_array('object', (array) ($node['type'] ?? []), true) || isset($node['properties'])) {
+ $result = new \stdClass;
+ foreach ($value as $key => $item) {
+ $result->{$key} = $this->schemaData($item, $node['properties'][$key] ?? [], $defs);
+ }
+
+ return $result;
+ }
+
+ return array_map(fn ($item) => $this->schemaData($item, $node['items'] ?? [], $defs), $value);
+ }
+
+ /** @return array */
+ public function validateSubmission(Opportunity $record): array
+ {
+ $values = app(OpportunityManagement::class)->values($record);
+ $payload = $values['canonical'] ?? [];
+ $this->validateSchema($payload, false);
+ $errors = [];
+ $check = function (bool $valid, string $path, string $message) use (&$errors): void {
+ if (! $valid) {
+ $errors['canonical.'.$path] = $message;
+ }
+ };
+ $check(($payload['opportunity_category'] ?? null) === $record->opportunity_category, 'opportunity_category', 'A categoria deve coincidir com o registo e a autorização.');
+ $check(($payload['promoter_id'] ?? null) === ($record->organization_id ?? (int) $record->owner_user_id), 'promoter_id', 'Use a organização representada ou o autor individual; não outra identidade.');
+ $sector = DB::table('sectors')->where('id', $payload['sector_id'])->whereNull('deleted_at')->where('is_active', true)->first();
+ $subsector = DB::table('economic_activities')->where('id', $payload['subsector_id'])->where('status', 'published')->first();
+ $activity = DB::table('economic_activities')->where('id', $payload['economic_activity_id'])->where('status', 'published')->first();
+ $root = $subsector?->parent_id ? DB::table('economic_activities')->where('id', $subsector->parent_id)->where('status', 'published')->first() : null;
+ $check($sector !== null && $root !== null && (int) $root->sector_id === (int) $sector->id
+ && $activity !== null && $activity->parent_id === $subsector->id && $activity->catalog_version_id === $root->catalog_version_id,
+ 'economic_activity_id', 'Sector → subsector → atividade requer referências publicadas da mesma versão e hierarquia.');
+ foreach (['internal_contact_id', 'public_contact_id'] as $field) {
+ if (! empty($payload[$field])) {
+ $contacts = DB::table('contacts')->where('contacts.id', $payload[$field])->whereNull('contacts.deleted_at');
+ if ($record->organization_id) {
+ $contacts->whereExists(fn ($q) => $q->selectRaw('1')->from('investor_contacts as ic')->join('investors as i', 'i.id', '=', 'ic.investor_id')
+ ->whereColumn('ic.contact_id', 'contacts.id')->where('i.organization_id', $record->organization_id)->whereNull('i.deleted_at'));
+ } else {
+ $contacts->where('source_system', 'portal-user-contact')->where('external_id', 'user:'.$record->owner_user_id);
+ }
+ $check($contacts->exists(), $field, 'Contacto inexistente ou sem relação com o Promotor.');
+ }
+ }
+ $resources = [];
+ foreach (['locations', 'documents', 'images'] as $kind) {
+ $table = app(OpportunityResources::class)->table($kind);
+ foreach ($payload[$kind] ?? [] as $index => $id) {
+ $row = DB::table($table)->where('id', $id)->where('opportunity_id', $record->id)->whereNull('deleted_at')->first();
+ $check($row !== null, "$kind.$index", 'Recurso inexistente, eliminado ou de outra oportunidade.');
+ if (! $row) {
+ continue;
+ }
+ $row->payload = json_decode($row->payload, true, 512, JSON_THROW_ON_ERROR);
+ if ($kind !== 'locations') {
+ $file = DB::table('documents')->where('id', $row->document_id)->first();
+ $check($file !== null && $file->deleted_at === null && $file->status === 'active' && $file->malware_scan_status === 'clean'
+ && hash_equals(trim($file->sha256), trim((string) $file->malware_scanned_sha256)), "$kind.$index", 'Original ativo com análise antimalware correspondente obrigatória.');
+ if ($file) {
+ // Verify actual bytes/cipher integrity as well as the recorded scan hash.
+ app(VerifiedDocumentBinary::class)->respond($file);
+ $row->sha256 = trim($file->sha256);
+ }
+ } else {
+ $location = $row->payload;
+ $check(! empty($location['district_id']) && ! empty($location['role']) && array_key_exists('is_primary', $location), "locations.$index", 'Localização requer distrito, papel e indicação de principal.');
+ app(InvestmentGeography::class)->selection($location, true);
+ $country = $location['country_code'] ?? null;
+ $check($country === 'MZ', "locations.$index.country_code", 'A hierarquia administrativa moçambicana deve declarar MZ; outros países exigem localização própria.');
+ }
+ $resources[$kind][$id] = (array) $row;
+ }
+ }
+ $locations = $resources['locations'] ?? [];
+ $primary = array_filter($locations, fn ($l) => $l['payload']['is_primary'] ?? false);
+ $check(count($primary) === 1, 'locations', 'Selecione exatamente uma localização principal.');
+ $check($payload['location_mode'] !== 'single' || count($locations) === 1, 'location_mode', 'Modo single exige uma localização.');
+ foreach ($payload['evidences'] as $i => $evidence) {
+ $check(isset($resources['documents'][$evidence['document_id']]), "evidences.$i.document_id", 'Evidência deve usar um documento ativo desta oportunidade incluído no contrato.');
+ }
+ $this->categoryRules($payload, $record, $resources, $errors);
+ app(OpportunityCategoryFields::class)->validate($payload, $record, $resources, $errors);
+ if ($errors) {
+ throw ValidationException::withMessages($errors);
+ }
+ ksort($payload);
+ $snapshot = ['adapter_version' => self::VERSION, 'schema_sha256' => hash_file('sha256', resource_path('data/investmoz-opportunity-modular.schema.json')),
+ 'payload' => $payload, 'resources' => $resources];
+ $snapshot['hash'] = hash('sha256', json_encode($snapshot, JSON_THROW_ON_ERROR));
+
+ return $snapshot;
+ }
+
+ /**
+ * @param array $p
+ * @param array $resources
+ * @param array $errors
+ */
+ private function categoryRules(array $p, Opportunity $record, array $resources, array &$errors): void
+ {
+ $category = $p['opportunity_category'];
+ if (in_array($category, ['concession', 'financing', 'supply', 'other'], true)) {
+ $errors['canonical.module_profile_version'] = '§25.4: não existe perfil modular aprovado/configurado. O rascunho permanece disponível; não inventar regras.';
+ }
+ foreach (['real_estate', 'land_rights', 'business_transaction'] as $module) {
+ $applicable = match ($module) {
+ 'real_estate' => ['real_estate'], 'land_rights' => ['land_rights'], default => ['business_sale', 'business_partnership', 'franchise']
+ };
+ if (isset($p[$module]) && ! in_array($category, $applicable, true)) {
+ $errors['canonical.'.$module] = 'Módulo incompatível com a categoria. Preserve-o noutra versão antes de mudar de categoria.';
+ }
+ }
+ if ($category === 'investment_project') {
+ $total = $p['total_investment'];
+ $sum = array_sum(array_column($p['investment_breakdown'], 'amount'));
+ $secured = array_sum(array_column($p['secured_financing'], 'amount'));
+ if (abs($sum - $total) > 0.010001 || $secured > $total || abs($p['funding_sought'] - ($total - $secured)) > 0.010001) {
+ $errors['canonical.investment_breakdown'] = 'Rubricas e financiamento devem reconciliar com o total (tolerância normativa 0,01).';
+ }
+ if (! in_array($p['maturity_stage'], array_keys(OpportunityMaturity::STAGES), true)) {
+ $errors['canonical.maturity_stage'] = 'Use um código explícito do catálogo de oito etapas; não reinterpretar a escala histórica.';
+ }
+ foreach (['investment_breakdown', 'secured_financing'] as $field) {
+ foreach ($p[$field] as $i => $amount) {
+ if ($amount['currency'] !== $p['currency']) {
+ $errors["canonical.$field.$i.currency"] = 'Moedas distintas requerem cenário/câmbio explícito; não somar valores de moedas diferentes.';
+ }
+ }
+ }
+ foreach ($p['markets'] as $i => $market) {
+ if (isset($market['country_code']) && Validator::make(['country' => $market['country_code']], ['country' => app(CountryCatalogue::class)->rule()])->fails()) {
+ $errors["canonical.markets.$i.country_code"] = 'Use país do catálogo ISO existente.';
+ }
+ }
+ }
+ if ($category === 'real_estate') {
+ $re = $p['real_estate'];
+ if (($re['transaction_type'] === 'sale' && ($re['price'] ?? 0) <= 0) || ($re['transaction_type'] === 'lease' && (($re['rent'] ?? 0) <= 0 || empty($re['rent_periodicity'])))) {
+ $errors['canonical.real_estate.price'] = 'Venda exige preço positivo; arrendamento exige renda positiva e periodicidade.';
+ }
+ if (in_array($re['construction_status'], ['completed', 'occupied', 'renovation'], true) && empty($re['property_condition'])) {
+ $errors['canonical.real_estate.property_condition'] = 'Imóvel existente exige condição identificada.';
+ }
+ if (in_array($re['construction_status'], ['planned', 'under_construction'], true) && empty($re['planning_permit_document_id'])) {
+ $errors['canonical.real_estate.planning_permit_document_id'] = 'Estado construtivo exige licença de construção (§25.1).';
+ }
+ if (in_array($re['construction_status'], ['completed', 'occupied', 'renovation'], true) && empty($re['use_license_document_id'])) {
+ $errors['canonical.real_estate.use_license_document_id'] = 'Imóvel existente exige licença de utilização aplicável (§25.1).';
+ }
+ foreach (['planning_permit_document_id', 'use_license_document_id'] as $field) {
+ if (! empty($re[$field]) && ! isset($resources['documents'][$re[$field]])) {
+ $errors['canonical.real_estate.'.$field] = 'Licença deve referir documento ativo desta oportunidade.';
+ }
+ }
+ }
+ if ($category === 'land_rights') {
+ $land = $p['land_rights'];
+ if (! empty($land['issuing_authority_id']) && ! DB::table('authorities')->where('id', $land['issuing_authority_id'])->where('status', 'published')->exists()) {
+ $errors['canonical.land_rights.issuing_authority_id'] = 'Entidade emissora deve usar autoridade canónica publicada.';
+ }
+ if (! empty($land['issue_date']) && ($land['issue_date'] > today()->toDateString() || (! empty($land['expiry_date']) && $land['expiry_date'] <= $land['issue_date']))) {
+ $errors['canonical.land_rights.issue_date'] = 'Emissão não futura e validade posterior à emissão.';
+ }
+ foreach ($land['parcels'] as $i => $parcel) {
+ if (! isset($resources['locations'][$parcel['location_id']])) {
+ $errors["canonical.land_rights.parcels.$i.location_id"] = 'Parcela deve usar uma localização desta oportunidade.';
+ }
+ try {
+ $g = DB::selectOne('SELECT ST_IsValid(g) AND NOT ST_IsEmpty(g) AND ST_GeometryType(g)=\'ST_MultiPolygon\' AND ST_XMin(Box3D(g))>=-180 AND ST_XMax(Box3D(g))<=180 AND ST_YMin(Box3D(g))>=-90 AND ST_YMax(Box3D(g))<=90 AS valid FROM (SELECT ST_SetSRID(ST_GeomFromGeoJSON(?),4326) g) s', [json_encode($parcel['geometry'])]);
+ if (! $g?->valid) {
+ throw new \RuntimeException;
+ }
+ } catch (\Throwable) {
+ $errors["canonical.land_rights.parcels.$i.geometry"] = 'Parcela requer MultiPolygon válido, não vazio, EPSG:4326; limite administrativo não é parcela.';
+ }
+ }
+ if (in_array($land['duat_status'], ['provisional', 'definitive'], true) && empty($land['duat_number'])) {
+ $errors['canonical.land_rights.duat_number'] = 'DUAT provisório/definitivo exige número e entidade emissora.';
+ }
+ }
+ if (isset($p['business_transaction'])) {
+ $business = $p['business_transaction'];
+ if ($business['legal_entity_id'] !== $record->organization_id || ! DB::table('organizations')->where('id', $business['legal_entity_id'])->whereNull('deleted_at')->exists()) {
+ $errors['canonical.business_transaction.legal_entity_id'] = 'Entidade ativa representada obrigatória.';
+ }
+ }
+ }
+
+ /** @param array $snapshot */
+ public function validatePublication(array $snapshot): void
+ {
+ $p = $snapshot['payload'];
+ $errors = [];
+ app(OpportunityCategoryFields::class)->publication($p, $errors);
+ foreach ($snapshot['resources']['documents'] ?? [] as $id => $document) {
+ if (! empty($document['payload']['valid_until']) && $document['payload']['valid_until'] < today()->toDateString()) {
+ $errors['documents.'.$id] = 'Documento incluído expirou; preserve o original e reveja a versão.';
+ }
+ }
+ if ($p['opportunity_category'] === 'land_rights') {
+ foreach ($p['land_rights']['required_authorizations'] as $i => $authorization) {
+ if (! in_array($authorization['status'] ?? '', ['approved', 'not_required'], true)
+ || (($authorization['status'] ?? '') === 'approved' && ! isset($snapshot['resources']['documents'][$authorization['document_id'] ?? '']))) {
+ $errors['land_rights.required_authorizations.'.$i] = 'Autorização externa pendente ou sem documento. Aprovação interna não substitui esse ato.';
+ }
+ }
+ foreach ($p['land_rights']['overlaps_conflicts'] as $i => $conflict) {
+ if (($conflict['type'] ?? '') !== 'none' && ($conflict['status'] ?? '') !== 'resolved') {
+ $errors['land_rights.overlaps_conflicts.'.$i] = 'Conflito impeditivo deve ser resolvido com evidência antes de publicar.';
+ }
+ }
+ }
+ if ($p['visibility'] === 'public') {
+ $images = $snapshot['resources']['images'] ?? [];
+ if (count(array_filter($images, fn ($image) => $image['payload']['is_cover'] ?? false)) !== 1) {
+ $errors['images'] = 'Publicação pública exige uma capa explícita.';
+ }
+ foreach ($images as $id => $image) {
+ $meta = $image['payload'];
+ if (empty($meta['alt_text']) || empty($meta['caption']) || empty($meta['rights_status']) || empty($meta['derivatives'])
+ || (! empty($meta['rights_valid_until']) && $meta['rights_valid_until'] < today()->toDateString())) {
+ $errors['images.'.$id] = 'Legenda, texto alternativo, direitos válidos e derivadas verificadas obrigatórios.';
+ }
+ foreach ($meta['derivatives'] ?? [] as $derived) {
+ $file = DB::table('documents')->where('id', $derived['document_id'])->whereNull('deleted_at')->where('status', 'active')->where('malware_scan_status', 'clean')->whereColumn('sha256', 'malware_scanned_sha256')->first();
+ if (! $file) {
+ $errors['images.'.$id] = 'Scan de uma derivada ainda não demonstrado.';
+ } else {
+ app(VerifiedDocumentBinary::class)->respond($file);
+ }
+ }
+ }
+ }
+ if ($errors) {
+ throw ValidationException::withMessages($errors);
+ }
+ }
+
+ /** @return list */
+ public function gates(Opportunity $record): array
+ {
+ return match ($record->opportunity_category) {
+ 'investment_project' => ['technical_review', 'legal_territorial_review'],
+ 'real_estate' => ['property_review', 'registry_urban_review', 'building_compliance_review'],
+ 'land_rights' => ['cadastral_screening', 'land_legal_review', 'community_environment_review', 'competent_authority_clearance'],
+ 'business_sale' => ['corporate_screening', 'financial_review', 'legal_tax_due_diligence', 'confidentiality_clearance'],
+ 'business_partnership' => ['corporate_screening', 'financial_review', 'partnership_governance_review', 'legal_tax_due_diligence'],
+ 'franchise' => ['brand_license_review', 'financial_review', 'franchise_legal_review', 'confidentiality_clearance'],
+ default => [],
+ };
+ }
+
+ /** Same exact projection for preview and publication; never expose private business analysis.
+ * @param array $payload
+ * @return array{title:string,summary:string,description:string} */
+ public function publicProjection(array $payload): array
+ {
+ $business = isset($payload['business_transaction']) && ($payload['visibility'] ?? '') === 'public';
+
+ return ['title' => (string) ($payload['official_title'] ?? ''), 'summary' => (string) ($business ? ($payload['business_transaction']['teaser'] ?? '') : ($payload['executive_summary'] ?? '')),
+ 'description' => (string) ($business ? ($payload['business_transaction']['teaser'] ?? '') : ($payload['demand_statement'] ?? ''))];
+ }
+
+ /** @return array */
+ public function options(User $actor, ?Opportunity $record): array
+ {
+ $orgs = array_values(array_unique(array_column(app(PortalProfileAccess::class)->navigation($actor)['contexts'] ?? [], 'organization_id')));
+ if ($record?->organization_id) {
+ $orgs = [$record->organization_id];
+ }
+ $contacts = DB::table('contacts')->whereNull('contacts.deleted_at')->where(function ($q) use ($orgs, $actor) {
+ $q->where(fn ($own) => $own->where('source_system', 'portal-user-contact')->where('external_id', 'user:'.$actor->id))
+ ->orWhereExists(fn ($i) => $i->selectRaw('1')->from('investor_contacts as ic')->join('investors as inv', 'inv.id', '=', 'ic.investor_id')->whereColumn('ic.contact_id', 'contacts.id')->whereIn('inv.organization_id', $orgs)->whereNull('inv.deleted_at'));
+ })->get(['id', 'full_name']);
+
+ return ['version' => self::VERSION, 'schema' => $this->schema(true)['$defs']['opportunityCreate'],
+ 'definitions' => $this->schema(true)['$defs'],
+ 'activities' => DB::table('economic_activities')->where('status', 'published')->get(['id', 'parent_id', 'sector_id', 'label_pt_mz', 'catalog_version_id']),
+ 'contacts' => $contacts, 'countries' => app(CountryCatalogue::class)->all(),
+ 'authorities' => DB::table('authorities')->where('status', 'published')->get(['id', 'label_pt_mz']),
+ 'gates' => $record ? $this->gates($record) : [], 'resources' => $record ? array_combine(['locations', 'documents', 'images'], array_map(fn ($k) => array_values(array_filter(app(OpportunityResources::class)->listing($record->id, $k), fn ($row) => empty($row->deleted_at))), ['locations', 'documents', 'images'])) : []];
+ }
+}
diff --git a/app/Services/OpportunityCategoryFields.php b/app/Services/OpportunityCategoryFields.php
new file mode 100644
index 00000000..446415a6
--- /dev/null
+++ b/app/Services/OpportunityCategoryFields.php
@@ -0,0 +1,277 @@
+ */
+ private function text(): array
+ {
+ return ['type' => 'string', 'minLength' => 1, 'maxLength' => 1000];
+ }
+
+ /** @return array */
+ private function doc(): array
+ {
+ return ['type' => 'string', 'format' => 'uuid'];
+ }
+
+ /** @return array */
+ private function money(): array
+ {
+ return ['type' => 'number', 'minimum' => 0];
+ }
+
+ /** @param array $properties
+ * @param list $required
+ * @return array */
+ private function object(array $properties, array $required = []): array
+ {
+ return ['type' => 'object', 'properties' => $properties, 'required' => $required, 'additionalProperties' => true];
+ }
+
+ /** @param array $properties
+ * @param list $required
+ * @return array */
+ private function rows(array $properties, array $required = []): array
+ {
+ return ['type' => 'array', 'items' => $this->object($properties, $required)];
+ }
+
+ /** Preserve normative artifact and legacy keys; enrich its runtime adapter explicitly.
+ * @param array $schema
+ * @return array */
+ public function enrich(array $schema): array
+ {
+ $s = $this->text();
+ $d = $this->doc();
+ $n = $this->money();
+ $date = ['type' => 'string', 'format' => 'date'];
+ $strings = ['type' => 'array', 'items' => $s];
+ $bool = ['type' => 'boolean'];
+ $valuation = $this->object(['value' => $n, 'date' => $date, 'method' => $s, 'appraiser' => $s, 'document_id' => $d, 'currency' => ['type' => 'string', 'pattern' => '^[A-Z]{3}$'], 'divergence_justification' => $s], ['value', 'date', 'method', 'appraiser', 'document_id']);
+ $defs = &$schema['$defs'];
+ $common = &$defs['opportunityCreate']['properties'];
+ foreach (['markets' => 'marketCreate', 'risks' => 'riskCreate', 'licenses' => 'licenseCreate', 'milestones' => 'milestoneCreate'] as $field => $def) {
+ $common[$field]['items'] = ['$ref' => '#/$defs/'.$def];
+ }
+ $common['maturity_stage']['enum'] = [...array_keys(OpportunityMaturity::STAGES), null];
+ $common['financial_indicators'] = $this->object(['npv' => ['type' => 'number'], 'irr' => ['type' => 'number'], 'payback_years' => $n, 'scenario' => $s, 'horizon_years' => ['type' => 'integer', 'minimum' => 1], 'currency' => ['type' => 'string', 'pattern' => '^[A-Z]{3}$'], 'discount_rate' => $n, 'model_document_id' => $d], ['npv', 'irr', 'payback_years', 'scenario', 'horizon_years', 'currency', 'discount_rate', 'model_document_id']);
+ $defs['milestoneCreate']['properties'] += ['start_date' => $date, 'end_date' => $date, 'responsible_name' => $s, 'dependencies' => $strings];
+ $defs['milestoneCreate']['required'] = array_values(array_unique([...$defs['milestoneCreate']['required'], 'start_date', 'end_date', 'responsible_name']));
+ $defs['riskCreate']['properties']['mitigation']['minLength'] = 1;
+ $re = &$defs['realEstateCreate']['properties'];
+ $re['valuation'] = $valuation;
+ $re['utilities'] = $this->rows(['type' => ['enum' => ['electricity', 'water', 'sanitation', 'telecommunications', 'access']], 'status' => ['enum' => ['existing', 'planned', 'unavailable']]], ['type', 'status']);
+ $re['encumbrances'] = $this->rows(['type' => $s, 'details' => $s, 'document_id' => $d], ['type']);
+ $re += ['title_document_id' => $d, 'title_holder_name' => $s, 'issuing_authority_id' => $d, 'expected_completion_date' => $date, 'occupancy_details' => $s, 'occupancy_document_id' => $d, 'amenities_other' => $s, 'urban_limit_document_id' => $d, 'max_built_area' => ['type' => 'number', 'exclusiveMinimum' => 0]];
+ $re['viewing'] = $this->object(['mode' => $s, 'contact_id' => $d, 'window' => $s, 'instructions' => $s]);
+ $defs['realEstateCreate']['required'] = [...$defs['realEstateCreate']['required'], 'title_document_id', 'title_holder_name', 'issuing_authority_id'];
+ $lr = &$defs['landRightsCreate']['properties'];
+ $lr['overlaps_conflicts'] = $this->rows(['type' => $s, 'status' => $s, 'details' => $s, 'resolution_document_id' => $d], ['type', 'status']);
+ $lr['required_authorizations'] = $this->rows(['name' => $s, 'authority_id' => $d, 'status' => ['enum' => ['pending', 'approved', 'rejected', 'not_required']], 'document_id' => $d, 'condition' => $s], ['name', 'status']);
+ $lr['community_consultation'] = $this->object(['status' => $s, 'minutes_document_id' => $d, 'participants' => $strings, 'map_document_id' => $d, 'commitments' => $s, 'date' => $date], ['status', 'minutes_document_id', 'participants', 'map_document_id', 'commitments', 'date']);
+ $lr['consideration'] = $this->object(['object' => ['enum' => ['improvements', 'assets', 'operation', 'partnership']], 'amount' => $n, 'currency' => ['type' => 'string', 'pattern' => '^[A-Z]{3}$']], ['object', 'amount', 'currency']);
+ $lr += ['holder_document_id' => $d, 'communities_affected' => $bool, 'exploitation_plan_required' => $bool];
+ $defs['landRightsCreate']['required'] = [...$defs['landRightsCreate']['required'], 'holder_document_id', 'communities_affected', 'exploitation_plan_required'];
+ $bt = &$defs['businessTransactionCreate']['properties'];
+ $bt['valuation'] = $valuation;
+ $bt['entity_registration'] = $this->object(['tax_identifier' => $s, 'registration_number' => $s, 'legal_document_id' => $d, 'beneficial_owner_document_id' => $d], ['tax_identifier', 'registration_number', 'legal_document_id', 'beneficial_owner_document_id']);
+ $bt['financial_periods'] = $this->rows(['year' => ['type' => 'integer', 'minimum' => 1900], 'currency' => ['type' => 'string', 'pattern' => '^[A-Z]{3}$'], 'revenue' => $n, 'profit' => ['type' => 'number'], 'ebitda' => ['type' => 'number'], 'assets' => $n, 'liabilities' => $n, 'cash_flow' => ['type' => 'number'], 'document_id' => $d], ['year', 'currency', 'revenue', 'profit', 'assets', 'liabilities', 'cash_flow', 'document_id']);
+ $bt['assets_liabilities'] = $this->object(['assets' => $s, 'excluded_assets' => $s, 'liabilities' => $s, 'guarantees' => $s, 'reconciliation_document_id' => $d], ['assets', 'excluded_assets', 'liabilities', 'guarantees', 'reconciliation_document_id']);
+ $bt['employees'] = $this->object(['total' => ['type' => 'integer', 'minimum' => 0], 'contracts' => $s, 'obligations' => $s, 'labor_liabilities' => $s], ['total', 'contracts', 'obligations', 'labor_liabilities']);
+ $bt['contracts_licenses'] = $this->rows(['name' => $s, 'transferability' => ['enum' => ['transferable', 'consent_required', 'not_transferable']], 'expiry_date' => $date, 'consent_document_id' => $d, 'document_id' => $d], ['name', 'transferability', 'expiry_date', 'document_id']);
+ $bt['litigation_contingencies'] = $this->rows(['type' => $s, 'details' => $s, 'value' => $n, 'status' => $s, 'probability' => ['type' => 'number', 'minimum' => 0, 'maximum' => 100], 'entity' => $s, 'document_id' => $d], ['type']);
+ $bt['partner_contribution'] = $this->object(['capital' => $n, 'assets' => $s, 'technology' => $s, 'market' => $s, 'management' => $s, 'calendar' => $s], ['capital', 'assets', 'technology', 'market', 'management', 'calendar']);
+ $bt['governance_rights'] = $this->object(['voting' => $s, 'board' => $s, 'reserved_matters' => $s, 'dividends' => $s, 'exit' => $s, 'deadlock' => $s], ['voting', 'board', 'reserved_matters', 'dividends', 'exit', 'deadlock']);
+ $bt['franchise_terms'] = $this->object(['brand' => $s, 'territory' => $s, 'term' => $s, 'initial_fee' => $n, 'royalties' => $s, 'support' => $s, 'exclusivity' => $s, 'renewal' => $s, 'termination' => $s, 'brand_license_document_id' => $d], ['brand', 'territory', 'term', 'initial_fee', 'royalties', 'support', 'exclusivity', 'renewal', 'termination', 'brand_license_document_id']);
+ $bt += ['available_financial_years' => ['type' => 'integer', 'minimum' => 1], 'nda_document_id' => $d, 'teaser' => $s];
+ $defs['businessTransactionCreate']['required'] = [...$defs['businessTransactionCreate']['required'], 'entity_registration', 'available_financial_years'];
+
+ return $schema;
+ }
+
+ /** @param array $p
+ * @param array $resources
+ * @param array $errors */
+ public function validate(array $p, Opportunity $record, array $resources, array &$errors): void
+ {
+ $fail = function (bool $ok, string $path, string $message) use (&$errors) {
+ if (! $ok) {
+ $errors['canonical.'.$path] = $message;
+ }
+ };
+ // Every nested reference belongs to this record, not merely to an existing document.
+ $walk = function (array $node, string $path = '') use (&$walk, $resources, $fail) {
+ foreach ($node as $key => $value) {
+ $here = ltrim($path.'.'.$key, '.');
+ if (is_array($value)) {
+ $walk($value, $here);
+ } elseif (is_string($key) && (str_ends_with($key, 'document_id') || in_array($key, ['image_id', 'location_id'], true)) && $value !== null && $value !== '') {
+ $kind = $key === 'image_id' ? 'images' : ($key === 'location_id' ? 'locations' : 'documents');
+ $fail(isset($resources[$kind][$value]), $here, 'Selecione um recurso ativo desta oportunidade, incluído no contrato.');
+ }
+ if ($key === 'authority_id' || $key === 'issuing_authority_id') {
+ $fail($value === null || DB::table('authorities')->where('id', $value)->where('status', 'published')->where('valid_from', '<=', today())->where(fn ($q) => $q->whereNull('valid_to')->orWhere('valid_to', '>=', today()))->exists(), $here, 'Selecione uma entidade emissora publicada e aplicável nesta data.');
+ }
+ }
+ };
+ $walk($p);
+ if (isset($p['real_estate']) || isset($p['business_transaction'])) {
+ $fail(isset($p['currency']) && is_string($p['currency']) && preg_match('/^[A-Z]{3}$/D', $p['currency']) === 1, 'currency', 'Indique a moeda de todos os valores desta versão.');
+ }
+ if ($p['opportunity_category'] === 'investment_project') {
+ $milestones = $p['milestones'];
+ $fail(count($milestones) >= 2, 'milestones', 'Indique pelo menos dois marcos.');
+ $titles = array_column($milestones, 'title');
+ $fail(count($titles) === count(array_unique($titles)), 'milestones', 'Os nomes dos marcos devem identificar cada dependência sem ambiguidade.');
+ $edges = [];
+ foreach ($milestones as $i => $m) {
+ $fail($m['end_date'] >= $m['start_date'], "milestones.$i.end_date", 'O fim não pode anteceder o início.');
+ $edges[$m['title']] = $m['dependencies'] ?? [];
+ $fail(array_diff($edges[$m['title']], $titles) === [], "milestones.$i.dependencies", 'Uma dependência deve indicar outro marco deste cronograma.');
+ }
+ $seen = [];
+ $active = [];
+ $visit = function ($title) use (&$visit, &$seen, &$active, $edges): bool {
+ if (isset($active[$title])) {
+ return false;
+ }if (isset($seen[$title])) {
+ return true;
+ }$active[$title] = true;
+ foreach ($edges[$title] ?? [] as $parent) {
+ if (! $visit($parent)) {
+ return false;
+ }
+ }unset($active[$title]);
+ $seen[$title] = true;
+
+ return true;
+ };
+ foreach ($titles as $title) {
+ $fail($visit($title), 'milestones', 'As dependências não podem formar um ciclo.');
+ }
+ foreach ($p['risks'] as $i => $risk) {
+ $fail(($risk['likelihood'] < 4 && $risk['severity'] < 4) || ! empty($risk['mitigation']), "risks.$i.mitigation", 'Risco com probabilidade ou gravidade alta exige mitigação.');
+ }
+ if (in_array($p['maturity_stage'], ['feasibility', 'structured', 'investment_ready', 'implementation', 'operational'], true)) {
+ $fail(! empty($p['financial_indicators']), 'financial_indicators', 'A partir de viabilidade, indique cenário, indicadores e modelo financeiro.');
+ $fail(count(array_filter($p['evidences'], fn ($e) => in_array($e['evidence_type'], ['feasibility_study', 'feasibility'], true))) > 0, 'evidences', 'Associe o estudo de viabilidade desta etapa.');
+ }
+ }
+ if (isset($p['real_estate'])) {
+ $re = $p['real_estate'];
+ $types = array_column($re['utilities'], 'type');
+ $fail(count($types) === 5 && count(array_unique($types)) === 5, 'real_estate.utilities', 'Declare os cinco serviços: eletricidade, água, saneamento, telecomunicações e acesso.');
+ if ($re['occupancy_status'] !== 'vacant') {
+ foreach (['occupancy_details', 'occupancy_document_id'] as $field) {
+ $fail(! empty($re[$field]), 'real_estate.'.$field, 'Ocupação exige detalhe contratual restrito e documento.');
+ }
+ }
+ if (in_array($re['construction_status'], ['planned', 'under_construction'], true)) {
+ $fail(! empty($re['expected_completion_date']) && $re['expected_completion_date'] >= today()->toDateString(), 'real_estate.expected_completion_date', 'Indique prazo de conclusão futuro ou atual.');
+ }
+ if (in_array('other', $re['amenities'] ?? [], true)) {
+ $fail(! empty($re['amenities_other']), 'real_estate.amenities_other', 'Descreva a comodidade indicada como outra.');
+ }
+ if (isset($re['max_built_area'])) {
+ $fail($re['built_area'] <= $re['max_built_area'], 'real_estate.built_area', 'A área excede o limite urbanístico declarado.');
+ $fail(! empty($re['urban_limit_document_id']), 'real_estate.urban_limit_document_id', 'Associe a fonte do limite urbanístico.');
+ }
+ foreach ($re['encumbrances'] as $i => $row) {
+ if ($row['type'] !== 'none') {
+ foreach (['details', 'document_id'] as $field) {
+ $fail(! empty($row[$field]), "real_estate.encumbrances.$i.$field", 'Ónus ou restrição exige descrição e documento.');
+ }
+ }
+ }
+ }
+ if (isset($p['land_rights'])) {
+ $lr = $p['land_rights'];
+ if (in_array($lr['duat_status'], ['provisional', 'definitive'], true)) {
+ $fail(! empty($lr['issuing_authority_id']), 'land_rights.issuing_authority_id', 'DUAT provisório/definitivo exige entidade emissora.');
+ if (! empty($lr['duat_number']) && ! empty($lr['issuing_authority_id'])) {
+ $fail(! Opportunity::whereKeyNot($record->id)->whereNotNull('owner_user_id')->whereRaw("management_draft->'canonical'->'land_rights'->>'duat_number'=?", [$lr['duat_number']])->whereRaw("management_draft->'canonical'->'land_rights'->>'issuing_authority_id'=?", [$lr['issuing_authority_id']])->whereNotIn('status', ['archived', 'rejected'])->exists(), 'land_rights.duat_number', 'Este número já está associado à mesma entidade emissora; reconciliar antes de submeter.');
+ }
+ }
+ if (in_array($lr['operation_type'], ['transfer_of_improvements', 'lease_of_improvements'], true)) {
+ $fail(! empty($lr['improvements']), 'land_rights.improvements', 'A operação sobre benfeitorias exige a respetiva descrição/evidência.');
+ }
+ foreach ($lr['improvements'] ?? [] as $i => $row) {
+ foreach (['assessed_value', 'currency', 'valuation_date', 'document_id', 'image_id'] as $field) {
+ $fail(isset($row[$field]), "land_rights.improvements.$i.$field", 'Benfeitoria exige valor, data, moeda, documento e fotografia.');
+ }
+ }
+ $fail(! $lr['exploitation_plan_required'] || ! empty($lr['exploitation_plan_document_id']), 'land_rights.exploitation_plan_document_id', 'Plano de exploração aplicável exige documento.');
+ $fail(! $lr['communities_affected'] || (! empty($lr['communities']) && ! empty($lr['community_consultation'])), 'land_rights.community_consultation', 'Comunidade afetada exige comunidade, representantes e consulta documentada.');
+ foreach ($lr['communities'] ?? [] as $i => $row) {
+ foreach (['representative_name', 'consultation_date', 'location_id'] as $field) {
+ $fail(! empty($row[$field]), "land_rights.communities.$i.$field", 'Identifique representante, data e localização da comunidade.');
+ }
+ }
+ }
+ if (isset($p['business_transaction'])) {
+ $bt = $p['business_transaction'];
+ $type = $bt['transaction_type'];
+ $allowed = match ($p['opportunity_category']) {
+ 'business_sale' => ['full_sale', 'partial_sale'],'business_partnership' => ['partnership', 'joint_venture'],'franchise' => ['franchise'],default => []
+ };
+ $fail(in_array($type, $allowed, true), 'business_transaction.transaction_type', 'Modalidade incompatível com esta categoria.');
+ $years = array_column($bt['financial_periods'], 'year');
+ $fail(count($years) >= min(3, $bt['available_financial_years']) && count($years) === count(array_unique($years)), 'business_transaction.financial_periods', 'Inclua pelo menos três exercícios quando existentes, sem repetir anos.');
+ foreach ($years as $i => $year) {
+ $fail($year <= (int) today()->format('Y'), "business_transaction.financial_periods.$i.year", 'Não apresente um exercício futuro como demonstração realizada.');
+ }
+ $fail($bt['litigation_contingencies'] !== [], 'business_transaction.litigation_contingencies', 'Declare contingências, incluindo explicitamente a ausência.');
+ foreach ($bt['litigation_contingencies'] as $i => $row) {
+ if ($row['type'] !== 'none') {
+ foreach (['value', 'status', 'probability', 'entity', 'document_id'] as $field) {
+ $fail(isset($row[$field]), "business_transaction.litigation_contingencies.$i.$field", 'Contingência exige valor, estado, probabilidade, responsável/evidência restrita.');
+ }
+ }
+ }
+ if ($bt['confidentiality_level'] === 'nda_required') {
+ $fail(! empty($bt['nda_document_id']), 'business_transaction.nda_document_id', 'Associe o acordo de confidencialidade aplicável.');
+ }
+ if ($p['visibility'] === 'public') {
+ $fail(! empty($bt['teaser']), 'business_transaction.teaser', 'Prepare o texto público sem informação confidencial.');
+ }
+ }
+ foreach (['real_estate', 'business_transaction'] as $module) {
+ if (isset($p[$module])) {
+ $v = $p[$module]['valuation'];
+ $fail($v['value'] > 0, "$module.valuation.value", 'Avaliação deve ter valor positivo.');
+ $fail($v['date'] <= today()->toDateString(), "$module.valuation.date", 'A data da avaliação não pode ser futura.');
+ // No arbitrary materiality threshold: reviewer determines divergence and its evidence.
+ }
+ }
+ }
+
+ /** @param array $p
+ * @param array $errors */
+ public function publication(array $p, array &$errors): void
+ {
+ if (isset($p['business_transaction'])) {
+ foreach ($p['business_transaction']['contracts_licenses'] as $i => $row) {
+ if ($row['expiry_date'] < today()->toDateString() || $row['transferability'] === 'not_transferable' || ($row['transferability'] === 'consent_required' && empty($row['consent_document_id']))) {
+ $errors["business_transaction.contracts_licenses.$i"] = 'Contrato/licença vencido, intransmissível ou sem consentimento exigido.';
+ }
+ }
+ }
+ if (isset($p['land_rights'])) {
+ $lr = $p['land_rights'];
+ if (! empty($lr['expiry_date']) && $lr['expiry_date'] < today()->toDateString()) {
+ $errors['land_rights.expiry_date'] = 'Direito expirado; decisão interna não renova o ato externo.';
+ }
+ if ($lr['communities_affected'] && ! in_array($lr['community_consultation']['status'] ?? '', ['completed', 'approved'], true)) {
+ $errors['land_rights.community_consultation'] = 'Consulta necessária ainda não concluída/documentada.';
+ }
+ }
+ }
+}
diff --git a/app/Services/OpportunityImageProcessor.php b/app/Services/OpportunityImageProcessor.php
index b447092d..231dec1d 100644
--- a/app/Services/OpportunityImageProcessor.php
+++ b/app/Services/OpportunityImageProcessor.php
@@ -20,7 +20,7 @@ class OpportunityImageProcessor
/** @param array $input */
public function prepare(User $actor, int $opportunityId, string $id, array $input): void
{
- abort_unless($actor->can('manage-portal'), 403);
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', Opportunity::withTrashed()->findOrFail($opportunityId));
abort_unless($this->available(), 423, 'GD/WebP não disponível neste processo. Original e metadados preservados; processamento pendente.');
$data = validator($input, ['etag' => 'required|string|size:64', 'version' => 'required|integer|min:1', 'reason' => 'required|string|min:20|max:1000'])->validate();
$stored = [];
@@ -28,6 +28,7 @@ class OpportunityImageProcessor
try {
DB::transaction(function () use ($actor, $opportunityId, $id, $data, &$stored, &$documents) {
$o = Opportunity::withTrashed()->whereKey($opportunityId)->lockForUpdate()->firstOrFail();
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', $o);
abort_if($o->trashed() || $o->status === 'archived', 409, 'Restaure antes de processar.');
abort_unless(hash_equals(app(OpportunityManagement::class)->etag($o), $data['etag']), 409, 'Conflito de versão; preserve os dados.');
$image = DB::table('opportunity_images')->where('opportunity_id', $opportunityId)->where('id', $id)->whereNull('deleted_at')->lockForUpdate()->first();
diff --git a/app/Services/OpportunityManagement.php b/app/Services/OpportunityManagement.php
index 44a71d77..ffbc5043 100644
--- a/app/Services/OpportunityManagement.php
+++ b/app/Services/OpportunityManagement.php
@@ -20,13 +20,15 @@ class OpportunityManagement
public const MATURITY_FIELDS = ['maturity_level', 'maturity_label', 'maturity_stage', 'maturity_catalogue_version'];
+ public const PRIVATE_DRAFT_FIELDS = [...self::MATURITY_FIELDS, 'real_estate', 'canonical'];
+
/** @return array */
public function values(Opportunity $record): array
{
$base = $record->only(self::FIELDS);
$draft = $record->management_draft ? json_decode($record->management_draft, true, 512, JSON_THROW_ON_ERROR) : [];
- return [...$base, ...($this->closed($record) ? $draft : array_intersect_key($draft, array_flip(self::MATURITY_FIELDS)))];
+ return [...$base, ...($this->closed($record) ? $draft : array_intersect_key($draft, array_flip(self::PRIVATE_DRAFT_FIELDS)))];
}
public function installed(): bool
@@ -47,7 +49,20 @@ class OpportunityManagement
/** @param array $input */
public function save(User $actor, array $input, ?int $id = null): Opportunity
{
- abort_unless($actor->can('manage-portal'), 403);
+ $access = app(PortalProfileAccess::class);
+ $profileCreation = $id === null && str_starts_with(request()->path(), 'minhas-oportunidades');
+ if ($id !== null) {
+ $existingRecord = Opportunity::withTrashed()->findOrFail($id);
+ $access->authorize($actor, 'edit', $existingRecord);
+ if ($existingRecord->owner_user_id !== null) {
+ abort_unless($access->canEdit($actor, $existingRecord, $input['opportunity_category'] ?? null), 403);
+ abort_if(array_key_exists('organization_id', $input) && $input['organization_id'] !== $existingRecord->organization_id, 403, 'A organização não pode ser alterada por edição.');
+ }
+ } elseif ($profileCreation) {
+ abort_unless($access->canCreate($actor, $input['organization_id'] ?? null, $input['opportunity_category'] ?? ''), 403);
+ } else {
+ abort_unless($access->legacyWriteAllowed($actor), 403, 'O papel v1 não usa a criação legada para contornar o seu âmbito.');
+ }
abort_unless($this->installed(), 503, 'Instalação autenticada ainda necessária.');
$data = Validator::make($input, [
'etag' => [$id ? 'required' : 'nullable', 'string', 'size:64'],
@@ -62,18 +77,30 @@ class OpportunityManagement
'expected_impact' => ['nullable', 'string', 'max:10000'],
'sector_id' => ['nullable', 'integer', Rule::exists('sectors', 'id')->whereNull('deleted_at')->where('is_active', true)],
'opportunity_category' => ['nullable', Rule::in(self::CATEGORIES)],
+ 'real_estate' => ['sometimes', 'array'],
+ 'canonical' => ['sometimes', 'array'],
'estimated_investment_amount' => ['nullable', 'regex:/^\d{1,16}(\.\d{1,2})?$/'],
'estimated_investment_currency' => ['nullable', 'in:MZN,USD,EUR,ZAR'],
'reason' => ['required', 'string', 'min:20', 'max:1000'],
+ 'organization_id' => ['nullable', 'uuid', Rule::exists('organizations', 'id')->whereNull('deleted_at')],
+ 'owner_user_id' => 'prohibited', 'workflow_context' => 'prohibited', 'status' => 'prohibited', 'first_submitted_at' => 'prohibited',
'province_id' => ['nullable', 'uuid'], 'district_id' => ['nullable', 'uuid'], 'admin_post_id' => ['nullable', 'uuid'], 'locality_id' => ['nullable', 'uuid'],
])->validate();
$data = app(OpportunityMaturity::class)->normalize($data);
+ if (array_key_exists('real_estate', $data)) {
+ $data['real_estate'] = app(OpportunityRealEstateDraft::class)->validate($data['real_estate']);
+ }
+ if (array_key_exists('canonical', $data)) {
+ $data['canonical'] = app(OpportunityCanonicalContract::class)->draft($data['canonical']);
+ }
- return DB::transaction(function () use ($actor, $data, $id) {
+ return DB::transaction(function () use ($actor, $data, $id, $profileCreation, $access) {
DB::select('SELECT pg_advisory_xact_lock(91026, 100000)');
if (! $id && ($existing = Opportunity::withTrashed()->where('management_creation_key', $data['creation_key'])->first())) {
+ $access->authorize($actor, 'view', $existing);
+ abort_unless($profileCreation === ($existing->owner_user_id !== null) && (! $profileCreation || $existing->organization_id === ($data['organization_id'] ?? null)), 409);
$snapshot = $this->values($existing);
- foreach (array_intersect_key($data, array_flip([...self::FIELDS, ...self::MATURITY_FIELDS])) as $key => $value) {
+ foreach (array_intersect_key($data, array_flip([...self::FIELDS, ...self::PRIVATE_DRAFT_FIELDS])) as $key => $value) {
if (($snapshot[$key] ?? null) != $value) {
throw ValidationException::withMessages(['creation_key' => 'Esta chave já foi utilizada com dados diferentes.']);
}
@@ -83,11 +110,33 @@ class OpportunityManagement
}
$record = $id ? Opportunity::withTrashed()->whereKey($id)->lockForUpdate()->firstOrFail() : new Opportunity;
if ($id) {
+ $access->authorize($actor, 'edit', $record);
$this->check($record, $data['etag']);
abort_if($record->trashed() || $record->status === 'archived', 409, 'Restaure antes de editar.');
}
$before = $record->getAttributes();
- $changes = array_intersect_key($data, array_flip([...self::FIELDS, ...self::MATURITY_FIELDS]));
+ $changes = array_intersect_key($data, array_flip([...self::FIELDS, ...self::PRIVATE_DRAFT_FIELDS]));
+ if (array_key_exists('canonical', $changes)) {
+ $previous = $record->exists ? $this->values($record) : [];
+ $changes['canonical'] = [...($previous['canonical'] ?? []), ...$changes['canonical']];
+ if (($changes['canonical']['opportunity_category'] ?? ($changes['opportunity_category'] ?? $record->opportunity_category)) !== ($changes['opportunity_category'] ?? $record->opportunity_category)) {
+ throw ValidationException::withMessages(['canonical.opportunity_category' => 'Contrato e registo devem usar a mesma categoria.']);
+ }
+ // One entry of common data feeds the existing fields; a closed/public version stays untouched.
+ foreach (['official_title' => 'title', 'executive_summary' => 'summary', 'demand_statement' => 'description', 'sector_id' => 'sector_id', 'promoter_type' => 'promoter_type'] as $source => $target) {
+ if (array_key_exists($source, $changes['canonical'])) {
+ $changes[$target] = $changes['canonical'][$source];
+ }
+ }
+ }
+ if (array_key_exists('real_estate', $changes)) {
+ $previousValues = $record->exists ? $this->values($record) : [];
+ $category = array_key_exists('opportunity_category', $data) ? $data['opportunity_category'] : ($previousValues['opportunity_category'] ?? null);
+ if ($category !== 'real_estate') {
+ throw ValidationException::withMessages(['real_estate' => 'O contrato imobiliário pertence à categoria real_estate.']);
+ }
+ $changes['real_estate'] = [...($previousValues['real_estate'] ?? []), ...$changes['real_estate']];
+ }
if (array_intersect_key($data, InvestmentGeography::FIELDS) !== []) {
$path = app(InvestmentGeography::class)->selection($data, true);
$changes['primary_territory_id'] = $path === [] ? null : $path[array_key_last($path)]->id;
@@ -102,6 +151,12 @@ class OpportunityManagement
$record->management_creation_key = $data['creation_key'];
$record->management_version = 1;
$record->estimated_investment_currency = null;
+ if ($profileCreation) {
+ abort_unless($access->canCreate($actor, $data['organization_id'] ?? null, $data['opportunity_category'] ?? ''), 403);
+ $record->owner_user_id = $actor->id;
+ $record->organization_id = $data['organization_id'] ?? null;
+ $record->workflow_context = ['policy_version' => PortalProfileAccess::VERSION, 'contributors' => [$actor->id]];
+ }
} else {
$record->management_version++;
}
@@ -111,17 +166,24 @@ class OpportunityManagement
$record->management_draft = json_encode([...$previous, ...$changes], JSON_THROW_ON_ERROR);
} else {
foreach ($changes as $key => $value) {
- if (in_array($key, ['maturity_stage', 'maturity_catalogue_version'], true) || (($changes['maturity_catalogue_version'] ?? null) === OpportunityMaturity::VERSION && in_array($key, ['maturity_level', 'maturity_label'], true))) {
+ if (in_array($key, ['real_estate', 'canonical', 'maturity_stage', 'maturity_catalogue_version'], true) || (($changes['maturity_catalogue_version'] ?? null) === OpportunityMaturity::VERSION && in_array($key, ['maturity_level', 'maturity_label'], true))) {
continue;
}
$record->{$key} = $value;
}
- if (isset($changes['maturity_catalogue_version'])) {
+ if (isset($changes['maturity_catalogue_version']) || array_key_exists('real_estate', $changes) || array_key_exists('canonical', $changes)) {
// The existing draft JSON holds the versioned catalogue; legacy columns stay intact.
$previous = $record->management_draft ? json_decode($record->management_draft, true, 512, JSON_THROW_ON_ERROR) : [];
- $record->management_draft = json_encode([...$previous, ...array_intersect_key($changes, array_flip(self::MATURITY_FIELDS))], JSON_THROW_ON_ERROR);
+ $record->management_draft = json_encode([...$previous, ...array_intersect_key($changes, array_flip(self::PRIVATE_DRAFT_FIELDS))], JSON_THROW_ON_ERROR);
}
}
+ if ($record->owner_user_id !== null) {
+ $context = $record->workflow_context ?? [];
+ unset($context['approval'], $context['reviews']);
+ $context['content_revision'] = ($context['content_revision'] ?? 0) + 1;
+ $context['contributors'] = array_values(array_unique([...($context['contributors'] ?? []), $actor->id]));
+ $record->workflow_context = $context;
+ }
$record->save();
$this->audit($record, $actor, $before, $id ? 'draft_updated' : 'draft_created', $data['reason']);
@@ -132,11 +194,13 @@ class OpportunityManagement
/** @param array $input */
public function lifecycle(User $actor, int $id, array $input): Opportunity
{
- abort_unless($actor->can('manage-portal'), 403);
- $data = Validator::make($input, ['etag' => ['required', 'string', 'size:64'], 'action' => ['required', 'in:delete,restore'], 'reason' => ['required', 'string', 'min:20', 'max:1000'], 'confirm' => ['required', 'accepted']])->validate();
+ abort_unless(app(PortalProfileAccess::class)->legacyWriteAllowed($actor), 403);
+ $actions = config('portal.opportunity_dashboard_access_enabled') ? 'in:delete,archive,restore' : 'in:delete,restore';
+ $data = Validator::make($input, ['etag' => ['required', 'string', 'size:64'], 'action' => ['required', $actions], 'reason' => ['required', 'string', 'min:20', 'max:1000'], 'confirm' => ['required', 'accepted']])->validate();
return DB::transaction(function () use ($actor, $id, $data) {
$record = Opportunity::withTrashed()->whereKey($id)->lockForUpdate()->firstOrFail();
+ abort_if($record->owner_user_id !== null, 403, 'A v1 exige pedido e decisão de arquivo; não concede exclusão ou restauro ao Promotor.');
$this->check($record, $data['etag']);
$before = $record->getAttributes();
if ($data['action'] === 'restore') {
@@ -152,8 +216,10 @@ class OpportunityManagement
}
} else {
abort_if($record->trashed() || $record->status === 'archived', 409, 'Registo já eliminado/arquivado.');
- if ($this->closed($record)) {
- $record->management_closed_once = true;
+ if ($data['action'] === 'archive' || $this->closed($record)) {
+ if ($this->closed($record)) {
+ $record->management_closed_once = true;
+ }
$record->status = 'archived';
} else {
$record->deleted_at = now();
diff --git a/app/Services/OpportunityManagementInstallation.php b/app/Services/OpportunityManagementInstallation.php
index f0f765b3..90b3606f 100644
--- a/app/Services/OpportunityManagementInstallation.php
+++ b/app/Services/OpportunityManagementInstallation.php
@@ -15,7 +15,12 @@ class OpportunityManagementInstallation
$files = [__FILE__, app_path('Models/Opportunity.php'), app_path('Services/OpportunityManagement.php'), app_path('Http/Controllers/OpportunityManagementController.php'), app_path('Http/Controllers/PortalManagementController.php'), database_path('migrations/'.self::MIGRATION.'.php'), base_path('routes/web.php'), resource_path('js/pages/management/opportunity-draft.tsx'), resource_path('js/pages/management/opportunities.tsx')];
$files[] = app_path('Services/OpportunityMaturity.php');
+ $files = [...$files, app_path('Services/OpportunityRealEstateDraft.php'), app_path('Http/Middleware/HandleInertiaRequests.php'), config_path('portal.php'),
+ resource_path('data/investmoz-opportunity-modular.schema.json'), resource_path('js/pages/dashboard.tsx'), resource_path('js/components/app-sidebar.tsx'), resource_path('js/types/opportunity-management.ts'), base_path('vite.config.ts')];
+ $files = [...$files, resource_path('js/lib/portal-navigation.ts'), resource_path('js/components/portal-grouped-menu.tsx')];
+
+ $files = [...$files, ...PortalProfileAccess::fingerprintFiles()];
return hash('sha256', json_encode(array_map(fn ($file) => hash_file('sha256', $file), $files), JSON_THROW_ON_ERROR));
}
diff --git a/app/Services/OpportunityProfileWorkflow.php b/app/Services/OpportunityProfileWorkflow.php
new file mode 100644
index 00000000..7e9910c1
--- /dev/null
+++ b/app/Services/OpportunityProfileWorkflow.php
@@ -0,0 +1,420 @@
+ */
+ public function actions(User $actor, Opportunity $record): array
+ {
+ if ($record->owner_user_id === null || ! $this->access->canView($actor, $record)) {
+ return [];
+ }
+ $actions = [];
+ $state = $this->access->state($record);
+ if ($this->access->scoped($actor, 'promoter', $record->organization_id, $record->opportunity_category)
+ && ($record->organization_id !== null || (int) $record->owner_user_id === $actor->id)
+ && $this->access->operational($actor, 'edit', $record->id)) {
+ if (in_array($state, ['draft', 'needs_information'], true)) {
+ $actions[] = 'submit';
+ }
+ if (in_array($state, ['approved', 'published', 'suspended'], true)) {
+ $actions[] = 'request_revision';
+ }
+ if (! in_array($state, ['archived', 'rejected'], true)) {
+ $actions[] = 'request_archive';
+ }
+ if ($state === 'rejected' && empty($record->workflow_context['appeal']['pending'])) {
+ $actions[] = 'appeal';
+ }
+ }
+ if ($this->access->mfa($actor) && ! $this->access->conflict($actor, $record)) {
+ if ($this->access->scoped($actor, 'validator', $record->organization_id, $record->opportunity_category) && $this->access->operational($actor, 'validate', $record->id)) {
+ if ($state === 'submitted') {
+ $actions[] = 'start_review';
+ }
+ if (in_array($state, ['submitted', 'in_review', 'information_pending'], true)) {
+ array_push($actions, 'request_correction', 'pending_opinion', 'reject', 'review_gate', 'approve');
+ if ($this->responsibility($actor, $record, 'validation_coordinator')) {
+ $actions[] = 'assign_review';
+ }
+ }
+ if ($state === 'rejected' && ($record->workflow_context['appeal']['pending'] ?? false)
+ && $this->responsibility($actor, $record, 'appeal_reviewer')
+ && (int) ($record->workflow_context['rejection']['actor_id'] ?? 0) !== $actor->id) {
+ array_push($actions, 'appeal_uphold', 'appeal_reopen');
+ }
+ if (count(array_filter($record->workflow_context['opinions'] ?? [], fn ($opinion) => ($opinion['recipient_id'] ?? 0) === $actor->id && ($opinion['status'] ?? '') === 'pending')) > 0) {
+ $actions[] = 'respond_opinion';
+ }
+ }
+ if ($this->access->scoped($actor, 'publisher', $record->organization_id, $record->opportunity_category)) {
+ if ($state === 'approved' && $this->access->operational($actor, 'publish', $record->id)
+ && (int) ($record->workflow_context['approval']['actor_id'] ?? 0) !== $actor->id) {
+ $actions[] = 'publish';
+ if ($this->responsibility($actor, $record, 'publication_coordinator')) {
+ $actions[] = 'assign_publication';
+ }
+ }
+ if ($this->access->operational($actor, 'archive', $record->id)) {
+ if ($record->status === 'published') {
+ $actions[] = 'suspend';
+ }
+ if ($state !== 'archived') {
+ $actions[] = 'archive';
+ }
+ }
+ }
+ }
+
+ if (isset($record->workflow_context['assignment']['assignee_user_id']) && (int) $record->workflow_context['assignment']['assignee_user_id'] !== $actor->id) {
+ $actions = array_values(array_diff($actions, ['start_review', 'request_correction', 'pending_opinion', 'reject', 'review_gate', 'approve']));
+ }
+ if (isset($record->workflow_context['publication_assignment']['assignee_user_id']) && (int) $record->workflow_context['publication_assignment']['assignee_user_id'] !== $actor->id) {
+ $actions = array_values(array_diff($actions, ['publish']));
+ }
+
+ return $actions;
+ }
+
+ /** Scoped names/IDs only; no secrets or implicit assignees.
+ * @return array */
+ public function participants(User $actor, Opportunity $record): array
+ {
+ $this->access->authorize($actor, 'view', $record);
+ if (! $this->access->has($actor, 'validator') && ! $this->access->has($actor, 'publisher')) {
+ return ['validators' => [], 'publishers' => []];
+ }
+ $result = ['validators' => [], 'publishers' => []];
+ foreach (User::whereNotNull('email_verified_at')->whereNotNull('two_factor_confirmed_at')->get() as $candidate) {
+ if ($this->access->conflict($candidate, $record)) {
+ continue;
+ }
+ foreach (['validator' => 'validators', 'publisher' => 'publishers'] as $role => $list) {
+ if ($this->access->scoped($candidate, $role, $record->organization_id, $record->opportunity_category) && $this->access->operational($candidate, $role === 'validator' ? 'validate' : 'publish', $record->id)) {
+ if ($role === 'publisher' && (int) ($record->workflow_context['approval']['actor_id'] ?? 0) === $candidate->id) {
+ continue;
+ }
+ $result[$list][] = ['id' => $candidate->id, 'name' => $candidate->name, 'technical' => $this->responsibility($candidate, $record, 'technical_reviewer'), 'legal' => $this->responsibility($candidate, $record, 'legal_reviewer')];
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /** @return list */
+ public function submissionGaps(Opportunity $record): array
+ {
+ try {
+ $this->contract->validateSubmission($record);
+
+ return [];
+ } catch (ValidationException $error) {
+ return array_keys($error->errors());
+ }
+ }
+
+ /** @param array $input */
+ public function transition(User $actor, int $id, array $input): Opportunity
+ {
+ $record = Opportunity::withTrashed()->findOrFail($id);
+ $this->access->authorize($actor, 'view', $record);
+ abort_unless($record->owner_user_id !== null && ! $record->trashed(), 409, 'Workflow apenas para registos explicitamente sujeitos à política.');
+ $data = Validator::make($input, ['etag' => 'required|string|size:64',
+ 'action' => 'required|in:submit,start_review,request_correction,pending_opinion,respond_opinion,reject,approve,publish,suspend,archive,request_archive,appeal,request_revision,review_gate,assign_review,assign_publication,appeal_uphold,appeal_reopen',
+ 'reason' => 'required|string|min:20|max:1000', 'correction_items' => 'sometimes|array', 'correction_items.*' => 'required|string|max:250',
+ 'gate' => 'sometimes|string|max:80', 'gate_decision' => 'sometimes|in:approved,rejected', 'assignee_user_id' => 'sometimes|integer|min:1',
+ 'opinion_id' => 'sometimes|uuid', 'recipient_user_id' => 'sometimes|integer|min:1',
+ 'evidence_document_ids' => 'sometimes|array', 'evidence_document_ids.*' => 'uuid', 'due_at' => 'prohibited',
+ 'confirm_publication' => 'sometimes|boolean', 'preview_hash' => 'sometimes|string|size:64',
+ ])->validate();
+ $action = $data['action'];
+ $this->authorizeAction($actor, $record, $action);
+
+ return DB::transaction(function () use ($actor, $id, $data, $action) {
+ $record = Opportunity::whereKey($id)->lockForUpdate()->firstOrFail();
+ abort_unless(hash_equals($this->management->etag($record), $data['etag']), 409, 'Versão alterada.');
+ $this->authorizeAction($actor, $record, $action);
+ $context = $record->workflow_context ?? [];
+ $state = $this->access->state($record);
+ $before = ['status' => $state, 'publication_status' => $record->status, 'version' => $record->management_version];
+ $from = match ($action) {
+ 'submit' => ['draft', 'needs_information'], 'start_review' => ['submitted'],
+ 'request_correction', 'pending_opinion', 'respond_opinion', 'reject', 'approve', 'review_gate', 'assign_review' => ['submitted', 'in_review', 'information_pending'],
+ 'publish' => ['approved'], 'suspend' => [$state],
+ 'assign_publication' => ['approved'],
+ 'request_revision' => ['approved', 'published', 'suspended'],
+ 'archive' => ['draft', 'submitted', 'in_review', 'information_pending', 'needs_information', 'approved', 'rejected', 'published', 'suspended'],
+ 'request_archive' => ['draft', 'submitted', 'in_review', 'information_pending', 'needs_information', 'approved', 'published', 'suspended'],
+ 'appeal', 'appeal_uphold', 'appeal_reopen' => ['rejected'],
+ default => [],
+ };
+ abort_unless(in_array($state, $from, true), 409, 'Transição incompatível com o estado atual.');
+ $decision = ['actor_id' => $actor->id, 'action' => $action, 'reason' => $data['reason'], 'at' => now()->toIso8601String(),
+ 'content_revision' => $context['content_revision'] ?? 1];
+ $next = $state;
+ $snapshot = [];
+ if (in_array($action, ['submit', 'review_gate', 'pending_opinion', 'respond_opinion', 'approve', 'publish'], true)) {
+ $snapshot = $this->contract->validateSubmission($record);
+ if ($action !== 'submit') {
+ abort_unless(hash_equals($context['submission']['hash'] ?? '', $snapshot['hash']), 409, 'Conteúdo ou recursos mudaram desde a submissão. Exige nova submissão/revisão.');
+ }
+ }
+ if ($action === 'submit') {
+ foreach ($context['opinions'] ?? [] as $opinionId => $opinion) {
+ if (($opinion['status'] ?? '') === 'pending') {
+ $context['opinions'][$opinionId]['status'] = 'superseded';
+ $this->tasks->complete($opinion['task_id'] ?? null, 'Nova versão submetida; parecer anterior preservado.');
+ }
+ }
+ $context['submission'] = [...$snapshot, ...$decision];
+ $context['sla'] = ['policy_version' => null, 'due_at' => null, 'status' => 'unconfigured'];
+ unset($context['approval'], $context['reviews'], $context['assignment'],$context['publication_assignment']);
+ $record->first_submitted_at ??= now()->toIso8601String();
+ $record->management_closed_once = true;
+ $record->workflow_context = $context;
+ $context['review_task_id'] = $this->tasks->ensure($record, 'opportunity_review', 'Validação da oportunidade '.$record->reference);
+ $this->tasks->complete($context['correction_task_id'] ?? null, $data['reason']);
+ $next = 'submitted';
+ } elseif ($action === 'start_review' || $action === 'assign_review') {
+ $subject = $action === 'start_review' ? $actor : User::whereKey($data['assignee_user_id'] ?? 0)->firstOrFail();
+ abort_unless($this->access->scoped($subject, 'validator', $record->organization_id, $record->opportunity_category)
+ && $this->access->operational($subject, 'validate', $record->id) && ! $this->access->conflict($subject, $record)
+ && $subject->two_factor_confirmed_at !== null, 403, 'Responsável requer papel válido, MFA configurado e independência.');
+ $context['review_task_id'] ??= $this->tasks->ensure($record, 'opportunity_review', 'Validação da oportunidade '.$record->reference);
+ $this->tasks->assign($record, $context['review_task_id'], $subject);
+ $context['assignment'] = [...$decision, 'assignee_user_id' => $subject->id];
+ $next = 'in_review';
+ } elseif ($action === 'review_gate') {
+ $gate = $data['gate'] ?? '';
+ abort_unless(in_array($gate, $this->contract->gates($record), true), 422, 'Gate não aplicável.');
+ $legal = preg_match('/legal|registry|authority|confidentiality|license/', $gate) === 1;
+ abort_unless($this->responsibility($actor, $record, $legal ? 'legal_reviewer' : 'technical_reviewer'), 403, 'Responsabilidade de revisão necessária.');
+ $documents = $data['evidence_document_ids'] ?? [];
+ abort_unless($documents !== [] && array_diff($documents, array_keys($snapshot['resources']['documents'] ?? [])) === [], 422, 'Selecione evidência documental desta versão.');
+ abort_unless(isset($data['gate_decision']), 422, 'Indique decisão fundamentada do gate.');
+ $context['reviews'][$gate] = [...$decision, 'decision' => $data['gate_decision'], 'hash' => $snapshot['hash'], 'evidence_document_ids' => $documents];
+ $next = 'in_review';
+ } elseif ($action === 'approve') {
+ abort_if(count(array_filter($context['opinions'] ?? [], fn ($o) => ($o['hash'] ?? '') === $snapshot['hash'] && ($o['status'] ?? '') === 'pending')) > 0, 422, 'Parecer da versão atual ainda pendente.');
+ abort_if(count(array_filter($context['opinions'] ?? [], fn ($o) => ($o['hash'] ?? '') === $snapshot['hash'] && ($o['response']['decision'] ?? '') === 'rejected')) > 0, 422, 'Parecer desfavorável exige correção e nova versão.');
+ foreach ($this->contract->gates($record) as $gate) {
+ $review = $context['reviews'][$gate] ?? [];
+ abort_unless(($review['decision'] ?? null) === 'approved' && ($review['hash'] ?? '') === $snapshot['hash'], 422, 'Gate '.$gate.' pendente, rejeitado ou de outra versão.');
+ $reviewer = User::whereKey($review['actor_id'])->firstOrFail();
+ abort_unless($this->access->scoped($reviewer, 'validator', $record->organization_id, $record->opportunity_category)
+ && ! $this->access->conflict($reviewer, $record) && $this->access->operational($reviewer, 'validate', $record->id)
+ && $this->responsibility($reviewer, $record, preg_match('/legal|registry|authority|confidentiality|license/', $gate) === 1 ? 'legal_reviewer' : 'technical_reviewer'), 403, 'Revisor revogado, sem responsabilidade ou com conflito.');
+ }
+ $context['approval'] = [...$decision, 'hash' => $snapshot['hash'], 'gates' => $context['reviews'] ?? []];
+ $this->tasks->complete($context['review_task_id'] ?? null, $data['reason']);
+ $record->workflow_context = $context;
+ $context['publication_task_id'] = $this->tasks->ensure($record, 'opportunity_publication', 'Preparação editorial '.$record->reference);
+ $next = 'approved';
+ } elseif ($action === 'assign_publication') {
+ $subject = User::whereKey($data['assignee_user_id'] ?? 0)->firstOrFail();
+ abort_unless($this->access->scoped($subject, 'publisher', $record->organization_id, $record->opportunity_category) && $this->access->operational($subject, 'publish', $record->id) && ! $this->access->conflict($subject, $record) && $subject->two_factor_confirmed_at !== null && (int) ($context['approval']['actor_id'] ?? 0) !== $subject->id, 403, 'Publicador exige MFA, âmbito e independência da aprovação.');
+ $context['publication_task_id'] ??= $this->tasks->ensure($record, 'opportunity_publication', 'Preparação editorial '.$record->reference);
+ $this->tasks->assign($record, $context['publication_task_id'], $subject);
+ $context['publication_assignment'] = [...$decision, 'assignee_user_id' => $subject->id];
+ } elseif ($action === 'publish') {
+ Validator::make($data, ['confirm_publication' => 'required|accepted', 'preview_hash' => 'required|string|size:64'])->validate();
+ $this->contract->validatePublication($snapshot);
+ abort_unless(hash_equals($snapshot['hash'], $data['preview_hash']), 409, 'Pré-visualização diferente da versão aprovada.');
+ abort_unless(($context['approval']['hash'] ?? '') === $snapshot['hash'], 409, 'Aprovação não corresponde ao conteúdo atual.');
+ foreach ($this->contract->gates($record) as $gate) {
+ $review = $context['approval']['gates'][$gate] ?? [];
+ abort_unless(($review['decision'] ?? null) === 'approved' && ($review['hash'] ?? '') === $snapshot['hash'], 422, 'Revisão aprovada desta versão necessária.');
+ $reviewer = User::whereKey($review['actor_id'])->firstOrFail();
+ abort_unless($this->access->scoped($reviewer, 'validator', $record->organization_id, $record->opportunity_category)
+ && ! $this->access->conflict($reviewer, $record) && $this->access->operational($reviewer, 'validate', $record->id)
+ && $this->responsibility($reviewer, $record, preg_match('/legal|registry|authority|confidentiality|license/', $gate) === 1 ? 'legal_reviewer' : 'technical_reviewer'), 403, 'Revisor revogado, sem responsabilidade ou com conflito na publicação.');
+ }
+ $approver = User::whereKey($context['approval']['actor_id'] ?? 0)->firstOrFail();
+ abort_unless($this->access->scoped($approver, 'validator', $record->organization_id, $record->opportunity_category)
+ && ! $this->access->conflict($approver, $record) && $this->access->operational($approver, 'validate', $record->id), 403, 'Aprovador revogado ou com conflito.');
+ $p = $snapshot['payload'];
+ if (! empty($p['review_due_date'])) {
+ abort_unless($p['review_due_date'] > today()->toDateString(), 422, 'Data de revisão deve ser futura.');
+ }
+ if (isset($p['business_transaction'])) {
+ abort_unless(in_array($p['business_transaction']['due_diligence_status'], ['data_room_ready', 'in_progress', 'completed', 'exceptions'], true), 422, 'Data room mínimo não preparado.');
+ }
+ if (isset($context['publication'])) {
+ $context['publication_history'][] = $context['publication'];
+ }
+ $context['publication'] = [...$decision, 'hash' => $snapshot['hash'], 'visibility' => $p['visibility'],
+ 'public_fields' => ['title', 'summary', 'description', 'sector_id', 'province', 'district']];
+ // Minimal public projection; contacts, valuations, evidence and originals remain private.
+ $projection = $this->contract->publicProjection($p);
+ $record->title = $projection['title'];
+ $record->summary = $projection['summary'];
+ $record->description = $projection['description'];
+ $record->sector_id = $p['sector_id'];
+ $locations = array_values(array_filter($snapshot['resources']['locations'], fn ($location) => $location['payload']['is_primary'] ?? false));
+ $location = $locations[0]; // The contract requires exactly one primary location.
+ $path = app(InvestmentGeography::class)->selection($location['payload'], true);
+ $last = array_key_last($path);
+ abort_unless($last !== null, 422, 'Localização principal sem hierarquia.');
+ $record->primary_territory_id = $path[$last]->id;
+ $record->province = $path[0]->name;
+ $record->district = $path[1]->name;
+ $record->geography_scope = $p['geographic_scope'] === 'national' ? 'national' : 'specific';
+ $record->published_at = now();
+ $record->status = 'published';
+ $next = 'published';
+ $this->tasks->complete($context['publication_task_id'] ?? null, $data['reason']);
+ } elseif ($action === 'pending_opinion') {
+ $gate = $data['gate'] ?? '';
+ abort_unless(in_array($gate, $this->contract->gates($record), true), 422, 'Indique a revisão aplicável ao parecer.');
+ $subject = User::whereKey($data['recipient_user_id'] ?? 0)->firstOrFail();
+ abort_unless($this->access->scoped($subject, 'validator', $record->organization_id, $record->opportunity_category)
+ && $this->access->operational($subject, 'validate', $record->id) && ! $this->access->conflict($subject, $record) && $subject->two_factor_confirmed_at !== null
+ && $this->responsibility($subject, $record, preg_match('/legal|registry|authority|confidentiality|license/', $gate) === 1 ? 'legal_reviewer' : 'technical_reviewer'), 403, 'Destinatário exige responsabilidade, MFA e independência.');
+ abort_if($subject->id === $actor->id, 422, 'O parecer deve ser solicitado a outro revisor.');
+ $opinionId = (string) Str::uuid();
+ $taskId = $this->tasks->ensure($record, 'opportunity_opinion:'.$opinionId, 'Parecer da oportunidade '.$record->reference);
+ $this->tasks->assign($record, $taskId, $subject);
+ $context['opinions'][$opinionId] = [...$decision, 'id' => $opinionId, 'recipient_id' => $subject->id, 'gate' => $gate, 'status' => 'pending', 'hash' => $snapshot['hash'], 'task_id' => $taskId];
+ $next = 'information_pending';
+ } elseif ($action === 'respond_opinion') {
+ $opinionId = $data['opinion_id'] ?? '';
+ $opinion = $context['opinions'][$opinionId] ?? [];
+ abort_unless(($opinion['recipient_id'] ?? 0) === $actor->id, 403, 'Parecer atribuído a outro revisor.');
+ abort_unless($this->responsibility($actor, $record, preg_match('/legal|registry|authority|confidentiality|license/', $opinion['gate'] ?? '') === 1 ? 'legal_reviewer' : 'technical_reviewer'), 403, 'Responsabilidade do parecer revogada.');
+ abort_unless(($opinion['status'] ?? '') === 'pending' && ($opinion['hash'] ?? '') === $snapshot['hash'], 409, 'Parecer encerrado ou de outra versão.');
+ $documents = $data['evidence_document_ids'] ?? [];
+ abort_unless(isset($data['gate_decision']) && $documents !== [] && array_diff($documents, array_keys($snapshot['resources']['documents'] ?? [])) === [], 422, 'Resposta exige decisão e documentos desta versão.');
+ $context['opinions'][$opinionId]['status'] = 'answered';
+ $context['opinions'][$opinionId]['response'] = [...$decision, 'decision' => $data['gate_decision'], 'evidence_document_ids' => $documents];
+ $this->tasks->complete($opinion['task_id'], $data['reason']);
+ $next = count(array_filter($context['opinions'], fn ($o) => ($o['hash'] ?? '') === $snapshot['hash'] && ($o['status'] ?? '') === 'pending')) > 0 ? 'information_pending' : 'in_review';
+ } elseif ($action === 'request_correction') {
+ abort_unless($data['correction_items'] ?? [], 422, 'Indique campos e documentos a corrigir.');
+ $this->tasks->complete($context['review_task_id'] ?? null, $data['reason']);
+ $context['correction_items'] = $data['correction_items'];
+ $context['correction_cycles'] = ($context['correction_cycles'] ?? 0) + 1;
+ $record->workflow_context = $context;
+ $context['correction_task_id'] = $this->tasks->ensure($record, 'opportunity_correction', 'Correções da oportunidade '.$record->reference);
+ $next = 'needs_information';
+ } elseif ($action === 'request_revision' || $action === 'appeal_reopen') {
+ $this->tasks->complete($context['review_task_id'] ?? null, $data['reason']);
+ $this->tasks->complete($context['publication_task_id'] ?? null, $data['reason']);
+ $context['decision_history'][] = ['approval' => $context['approval'] ?? null, 'reviews' => $context['reviews'] ?? null, 'submission' => $context['submission'] ?? null];
+ unset($context['approval'], $context['reviews']);
+ $next = 'needs_information';
+ } elseif ($action === 'request_archive') {
+ $context['request_archive'] = $decision;
+ } elseif ($action === 'appeal') {
+ abort_if($context['appeal']['pending'] ?? false, 409, 'Recurso já pendente.');
+ $context['appeal'] = [...$decision, 'pending' => true];
+ $context['appeal_task_id'] = $this->tasks->ensure($record, 'opportunity_appeal', 'Recurso da oportunidade '.$record->reference);
+ } elseif ($action === 'appeal_uphold') {
+ $next = 'rejected';
+ } else {
+ $next = match ($action) {
+ 'reject' => 'rejected', 'suspend' => 'suspended', 'archive' => 'archived'
+ };
+ if ($action === 'reject') {
+ $context['rejection'] = $decision;
+ $this->tasks->complete($context['review_task_id'] ?? null, $data['reason']);
+ }
+ if (in_array($action, ['suspend', 'archive'], true)) {
+ $record->status = $next;
+ foreach (['review_task_id', 'correction_task_id', 'publication_task_id', 'appeal_task_id'] as $task) {
+ $this->tasks->complete($context[$task] ?? null, $data['reason']);
+ }
+ }
+ }
+ if (in_array($action, ['appeal_uphold', 'appeal_reopen'], true)) {
+ $context['appeal']['pending'] = false;
+ $context['appeal']['decision'] = $decision;
+ $this->tasks->complete($context['appeal_task_id'] ?? null, $data['reason']);
+ }
+ if (in_array($action, ['request_correction', 'reject'], true)) {
+ unset($context['approval'], $context['reviews']);
+ }
+ if (in_array($action, ['request_correction', 'reject', 'suspend', 'archive', 'request_revision', 'appeal_reopen'], true)) {
+ foreach ($context['opinions'] ?? [] as $opinionId => $opinion) {
+ if (($opinion['status'] ?? '') === 'pending') {
+ $context['opinions'][$opinionId]['status'] = 'superseded';
+ $this->tasks->complete($opinion['task_id'] ?? null, $data['reason']);
+ }
+ }
+ }
+ $context['working_state'] = $next;
+ $context['last_decision'] = $decision;
+ $context['events'][] = [...$decision, 'from' => $state, 'to' => $next];
+ if ($record->status !== 'published' || in_array($action, ['suspend', 'archive'], true)) {
+ $record->status = $next;
+ }
+ $record->management_version++;
+ $record->workflow_context = $context;
+ $record->save();
+ $this->access->audit($actor, 'workflow_'.$action, ['record_id' => $record->id, 'before' => $before,
+ 'after' => ['status' => $next, 'publication_status' => $record->status, 'version' => $record->management_version], 'reason' => $data['reason']]);
+
+ return $record;
+ });
+ }
+
+ private function responsibility(User $actor, Opportunity $record, string $name): bool
+ {
+ foreach ($this->access->grants($actor, $name === 'publication_coordinator' ? 'publisher' : 'validator') as $grant) {
+ if (($grant->organization_id === null || $grant->organization_id === $record->organization_id)
+ && in_array($record->opportunity_category, json_decode($grant->opportunity_types, true), true)
+ && in_array($name, json_decode($grant->responsibilities, true), true)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private function authorizeAction(User $actor, Opportunity $record, string $action): void
+ {
+ $this->access->authorize($actor, 'view', $record);
+ $promoter = $this->access->scoped($actor, 'promoter', $record->organization_id, $record->opportunity_category)
+ && ($record->organization_id !== null || (int) $record->owner_user_id === $actor->id);
+ if (in_array($action, ['submit', 'request_archive', 'appeal', 'request_revision'], true)) {
+ abort_unless($promoter && $this->access->operational($actor, 'edit', $record->id), 403);
+ } else {
+ $role = in_array($action, ['publish', 'assign_publication', 'suspend', 'archive'], true) ? 'publisher' : 'validator';
+ $operation = $role === 'publisher' ? (in_array($action, ['publish', 'assign_publication'], true) ? 'publish' : 'archive') : 'validate';
+ abort_unless($this->access->scoped($actor, $role, $record->organization_id, $record->opportunity_category)
+ && $this->access->mfa($actor) && $this->access->operational($actor, $operation, $record->id) && ! $this->access->conflict($actor, $record), 403, 'Papel, MFA e independência necessários.');
+ if ($action === 'publish') {
+ abort_if((int) ($record->workflow_context['approval']['actor_id'] ?? 0) === $actor->id, 403, 'O aprovador não publica a mesma versão.');
+ abort_if(isset($record->workflow_context['publication_assignment']['assignee_user_id']) && (int) $record->workflow_context['publication_assignment']['assignee_user_id'] !== $actor->id, 403, 'Publicação atribuída a outro Publicador; requer reatribuição explícita.');
+ }
+ if ($action === 'assign_publication') {
+ abort_unless($this->responsibility($actor, $record, 'publication_coordinator'), 403);
+ }
+ if ($action === 'assign_review') {
+ abort_unless($this->responsibility($actor, $record, 'validation_coordinator'), 403);
+ }
+ if (in_array($action, ['start_review', 'review_gate', 'request_correction', 'pending_opinion', 'reject', 'approve'], true)
+ && isset($record->workflow_context['assignment']['assignee_user_id'])) {
+ abort_unless((int) $record->workflow_context['assignment']['assignee_user_id'] === $actor->id, 403, 'Tarefa atribuída a outro Validador; o coordenador deve registar a reatribuição.');
+ }
+ if (in_array($action, ['appeal_uphold', 'appeal_reopen'], true)) {
+ abort_unless($this->responsibility($actor, $record, 'appeal_reviewer') && ($record->workflow_context['appeal']['pending'] ?? false)
+ && (int) ($record->workflow_context['rejection']['actor_id'] ?? 0) !== $actor->id, 403, 'Recurso exige instância independente da rejeição.');
+ }
+ if ($action === 'suspend') {
+ abort_unless($record->status === 'published', 409);
+ }
+ }
+ }
+}
diff --git a/app/Services/OpportunityRealEstateDraft.php b/app/Services/OpportunityRealEstateDraft.php
new file mode 100644
index 00000000..bfbf8b91
--- /dev/null
+++ b/app/Services/OpportunityRealEstateDraft.php
@@ -0,0 +1,90 @@
+ $values
+ * @return array
+ */
+ public function validate(array $values): array
+ {
+ abort_unless(config('portal.opportunity_specialized_drafts_enabled'), 422, 'Campos especializados ainda não disponibilizados neste ambiente.');
+ $bytes = file_get_contents(resource_path('data/investmoz-opportunity-modular.schema.json'));
+ if ($bytes === false) {
+ throw new \RuntimeException('Normative opportunity schema unavailable.');
+ }
+ $schema = json_decode($bytes, true, 512, JSON_THROW_ON_ERROR);
+ $properties = $schema['$defs']['realEstatePatch']['properties'];
+ if ($values === [] || array_diff(array_keys($values), array_keys($properties))) {
+ throw ValidationException::withMessages(['real_estate' => 'Indique campos do contrato imobiliário; campos desconhecidos ou de resposta não são graváveis.']);
+ }
+ $errors = [];
+ foreach ($values as $key => $value) {
+ $this->check($value, $properties[$key], 'real_estate.'.$key, $errors);
+ }
+ if ($errors) {
+ throw ValidationException::withMessages($errors);
+ }
+
+ return $values;
+ }
+
+ /**
+ * @param array $schema
+ * @param array $errors
+ */
+ private function check(mixed $value, array $schema, string $path, array &$errors): void
+ {
+ $types = (array) ($schema['type'] ?? []);
+ $valid = $types === [] || array_filter($types, fn ($type) => match ($type) {
+ 'null' => $value === null,
+ 'string' => is_string($value),
+ 'integer' => is_int($value),
+ 'number' => is_int($value) || is_float($value),
+ 'boolean' => is_bool($value),
+ 'array' => is_array($value) && array_is_list($value),
+ // Laravel request arrays represent JSON objects, including empty ones.
+ 'object' => is_array($value) && ($value === [] || ! array_is_list($value)),
+ default => false,
+ }) !== [];
+ if (! $valid || (isset($schema['enum']) && ! in_array($value, $schema['enum'], true))) {
+ $errors[$path] = 'Tipo ou valor fora do contrato imobiliário §26.';
+
+ return;
+ }
+ if ($value === null) {
+ return;
+ }
+ $rules = [];
+ foreach (['minLength' => 'min', 'maxLength' => 'max', 'minItems' => 'min'] as $keyword => $rule) {
+ if (isset($schema[$keyword])) {
+ $rules[] = $rule.':'.$schema[$keyword];
+ }
+ }
+ if (in_array('number', $types, true) || in_array('integer', $types, true)) {
+ $rules[] = 'numeric';
+ foreach (['minimum' => 'min', 'maximum' => 'max', 'exclusiveMinimum' => 'gt'] as $keyword => $rule) {
+ if (isset($schema[$keyword])) {
+ $rules[] = $rule.':'.$schema[$keyword];
+ }
+ }
+ }
+ if (($schema['format'] ?? null) === 'uuid') {
+ $rules[] = 'uuid';
+ }
+ if ($rules && Validator::make(['value' => $value], ['value' => $rules])->fails()) {
+ $errors[$path] = 'Valor fora dos limites/formato do contrato imobiliário §26.';
+ }
+ if (isset($schema['items']) && is_array($value)) {
+ foreach ($value as $index => $item) {
+ $this->check($item, $schema['items'], $path.'.'.$index, $errors);
+ }
+ }
+ }
+}
diff --git a/app/Services/OpportunityResourceInstallation.php b/app/Services/OpportunityResourceInstallation.php
index 5c0f9da1..d73d144d 100644
--- a/app/Services/OpportunityResourceInstallation.php
+++ b/app/Services/OpportunityResourceInstallation.php
@@ -26,10 +26,16 @@ class OpportunityResourceInstallation
$files = [...$files, app_path('Services/ExistingBusinessIntake.php'), resource_path('js/pages/land-assistance/case.tsx')];
$files = [...$files, resource_path('js/pages/investment/detail.tsx'), resource_path('js/pages/partnerships/catalogue.tsx')];
- $files = [...$files, app_path('Services/VerifiedDocumentBinary.php'), app_path('Services/TerritoryGeometryImport.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), config_path('geometry-import.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
+ $files = [...$files, app_path('Services/VerifiedDocumentBinary.php'), app_path('Console/Commands/ImportDocumentBatch.php'), app_path('Services/TerritoryGeometryImport.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), config_path('geometry-import.php'), config_path('geometry-correspondences.php'), app_path('Http/Controllers/PartnershipExchangeController.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
base_path('bootstrap/app.php'), app_path('Providers/FortifyServiceProvider.php'), config_path('fortify.php'),
resource_path('js/pages/auth/login.tsx'), resource_path('js/pages/auth/two-factor-challenge.tsx')];
+ $files = [...$files, app_path('Services/OpportunityRealEstateDraft.php'), app_path('Http/Middleware/HandleInertiaRequests.php'), config_path('portal.php'),
+ resource_path('data/investmoz-opportunity-modular.schema.json'), resource_path('js/pages/dashboard.tsx'), resource_path('js/components/app-sidebar.tsx'), resource_path('js/types/opportunity-management.ts'), base_path('vite.config.ts')];
+
+ $files = [...$files, resource_path('js/lib/portal-navigation.ts'), resource_path('js/components/portal-grouped-menu.tsx')];
+
+ $files = [...$files, ...PortalProfileAccess::fingerprintFiles()];
return hash('sha256', json_encode(array_map(fn ($file) => hash_file('sha256', $file), $files), JSON_THROW_ON_ERROR));
}
diff --git a/app/Services/OpportunityResources.php b/app/Services/OpportunityResources.php
index dbe13214..43ed81d2 100644
--- a/app/Services/OpportunityResources.php
+++ b/app/Services/OpportunityResources.php
@@ -50,7 +50,7 @@ class OpportunityResources
/** @param array $input */
public function save(User $actor, int $opportunityId, string $kind, array $input, ?UploadedFile $file = null, ?string $id = null): \stdClass
{
- abort_unless($actor->can('manage-portal'), 403);
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', Opportunity::withTrashed()->findOrFail($opportunityId));
abort_unless($this->installed(), 503);
$table = $this->table($kind);
$data = Validator::make($input, [
@@ -69,6 +69,7 @@ class OpportunityResources
try {
$result = DB::transaction(function () use ($actor, $opportunityId, $kind, $table, $data, $payload, $file, $id, $stored, $documentId) {
$opportunity = $this->lock($opportunityId, $data['etag']);
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', $opportunity);
$record = $id ? DB::table($table)->where('id', $id)->where('opportunity_id', $opportunityId)->lockForUpdate()->first() : null;
abort_if($id && ! $record, 404);
abort_if($record && ($record->deleted_at || (int) $record->version !== (int) $data['version']), 409, 'Recurso alterado ou eliminado; preserve o preenchimento e reveja a versão.');
@@ -147,11 +148,12 @@ class OpportunityResources
/** @param array $input */
public function lifecycle(User $actor, int $opportunityId, string $kind, string $id, array $input): void
{
- abort_unless($actor->can('manage-portal'), 403);
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', Opportunity::withTrashed()->findOrFail($opportunityId));
abort_unless($this->installed(), 503);
$data = Validator::make($input, ['etag' => 'required|string|size:64', 'version' => 'required|integer|min:1', 'action' => 'required|in:delete,restore', 'reason' => 'required|string|min:20|max:1000', 'confirm' => 'required|accepted'])->validate();
DB::transaction(function () use ($actor, $opportunityId, $kind, $id, $data) {
$opportunity = $this->lock($opportunityId, $data['etag']);
+ app(PortalProfileAccess::class)->authorize($actor, 'edit', $opportunity);
$table = $this->table($kind);
$record = DB::table($table)->where('id', $id)->where('opportunity_id', $opportunityId)->lockForUpdate()->first();
abort_unless($record !== null, 404);
@@ -210,6 +212,7 @@ class OpportunityResources
{
$rules = ['title' => 'nullable|string|max:120', 'source_reference' => 'nullable|string|max:2000', 'source_date' => 'nullable|date_format:Y-m-d', 'visibility' => 'nullable|in:internal,authenticated,public'];
if ($kind === 'locations') {
+ $rules += ['country_code' => ['nullable', app(CountryCatalogue::class)->rule()]];
$rules += ['province_id' => 'nullable|uuid', 'district_id' => 'nullable|uuid', 'admin_post_id' => 'nullable|uuid', 'locality_id' => 'nullable|uuid', 'role' => 'nullable|in:headquarters,production,raw_material,storage,logistics,market,support,other', 'role_description' => 'nullable|string|max:1000', 'operational_unit' => 'nullable|string|max:120', 'is_primary' => 'nullable|boolean', 'address' => 'nullable|string|max:300', 'geometry' => 'nullable|array', 'area_value' => 'nullable|numeric|gt:0', 'area_unit' => 'nullable|in:sqm,ha,sqkm', 'allocation_percentage' => 'nullable|numeric|between:0,100', 'territorial_purpose' => 'nullable|in:implementation,context,impact,coverage', 'multi_district_rationale' => 'nullable|string|max:1000'];
} elseif ($kind === 'images') {
$rules += ['role' => 'nullable|in:cover,gallery,location,asset,product,plan,rendering,evidence,other', 'role_description' => 'nullable|string|max:1000', 'is_cover' => 'nullable|boolean', 'caption' => 'nullable|string|max:300', 'alt_text' => 'nullable|string|max:250', 'location_id' => ['nullable', 'uuid', Rule::exists('opportunity_location_drafts', 'id')->where('opportunity_id', $opportunityId)->whereNull('deleted_at')], 'captured_at' => 'nullable|date_format:Y-m-d|before_or_equal:today', 'author_source' => 'nullable|string|max:150', 'rights_status' => 'nullable|in:owned,licensed,authorized,public_domain', 'rights_document_id' => ['nullable', 'uuid', Rule::exists('opportunity_documents', 'id')->where('opportunity_id', $opportunityId)->whereNull('deleted_at')], 'rights_valid_until' => 'nullable|date_format:Y-m-d', 'sort_order' => 'nullable|integer|min:0'];
diff --git a/app/Services/OpportunityWorkflowTasks.php b/app/Services/OpportunityWorkflowTasks.php
new file mode 100644
index 00000000..d45d78c7
--- /dev/null
+++ b/app/Services/OpportunityWorkflowTasks.php
@@ -0,0 +1,49 @@
+id.':'.$kind.':'.($record->workflow_context['content_revision'] ?? 1);
+ $existing = DB::table('tasks')->where('source_system', 'opportunity-workflow')->where('external_id', $key)->first();
+ if ($existing) {
+ return $existing->id;
+ }
+ $id = (string) Str::uuid();
+ DB::table('tasks')->insert(['id' => $id, 'source_system' => 'opportunity-workflow', 'external_id' => $key,
+ 'correlation_id' => $record->management_creation_key, 'task_type' => $kind, 'title' => $title,
+ 'status' => 'open', 'due_at' => null, 'assignee_user_id' => null, 'data_classification' => 'restricted']);
+
+ return $id;
+ }
+
+ public function assign(Opportunity $record, string $taskId, User $subject): void
+ {
+ abort_unless(DB::table('tasks')->where('id', $taskId)->where('source_system', 'opportunity-workflow')
+ ->where('external_id', 'like', 'portal-opportunity:'.$record->id.':%')->whereIn('status', ['open', 'in_progress'])->exists(), 409, 'Tarefa não pertence à versão aberta.');
+ DB::table('tasks')->where('id', $taskId)->update(['assignee_user_id' => $subject->id, 'status' => 'in_progress', 'version_no' => DB::raw('version_no+1')]);
+ }
+
+ public function complete(?string $taskId, string $outcome): void
+ {
+ if ($taskId) {
+ DB::table('tasks')->where('id', $taskId)->where('source_system', 'opportunity-workflow')->whereIn('status', ['open', 'in_progress'])
+ ->update(['status' => 'done', 'outcome' => $outcome, 'completed_at' => now(), 'version_no' => DB::raw('version_no+1')]);
+ }
+ }
+
+ /** @return list<\stdClass> */
+ public function listing(Opportunity $record): array
+ {
+ return array_values(DB::table('tasks')->where('source_system', 'opportunity-workflow')->where('external_id', 'like', 'portal-opportunity:'.$record->id.':%')
+ ->get(['id', 'task_type', 'status', 'title', 'assignee_user_id', 'due_at', 'completed_at', 'outcome'])->all());
+ }
+}
diff --git a/app/Services/PortalProfileAccess.php b/app/Services/PortalProfileAccess.php
new file mode 100644
index 00000000..eb849f92
--- /dev/null
+++ b/app/Services/PortalProfileAccess.php
@@ -0,0 +1,262 @@
+ */
+ public static function fingerprintFiles(): array
+ {
+ return [__FILE__, app_path('Models/User.php'), app_path('Models/Opportunity.php'), config_path('portal.php'), base_path('routes/web.php'),
+ app_path('Http/Middleware/HandleInertiaRequests.php'), app_path('Services/OpportunityManagement.php'),
+ app_path('Services/OpportunityResources.php'), app_path('Services/OpportunityImageProcessor.php'),
+ app_path('Services/PortalProfileAdministration.php'), app_path('Services/PortalSuperusers.php'),
+ app_path('Services/OpportunityProfileWorkflow.php'), app_path('Http/Controllers/PortalProfileController.php'), app_path('Http/Controllers/DashboardController.php'),
+ app_path('Http/Controllers/OpportunityManagementController.php'),
+ app_path('Services/OpportunityCanonicalContract.php'), app_path('Services/OpportunityCategoryFields.php'), app_path('Services/OpportunityWorkflowTasks.php'), base_path('composer.json'), base_path('composer.lock'),
+ resource_path('data/investmoz-opportunity-modular.schema.json'), resource_path('js/components/opportunity-canonical-fields.tsx'), resource_path('js/components/opportunity-parcel-geometry.tsx'),
+ app_path('Http/Controllers/OpportunityResourceController.php'),
+ app_path('Http/Controllers/InvestmentTerritoryController.php'),
+ app_path('Http/Middleware/PortalProfileSession.php'), app_path('Http/Middleware/ProtectProfileOpportunity.php'),
+ app_path('Http/Middleware/ProtectPrivilegedIdentity.php'), app_path('Http/Middleware/EnsurePortalProfiles.php'),
+ app_path('Http/Middleware/AuditProfileDecision.php'), app_path('Providers/AppServiceProvider.php'),
+ database_path('migrations/2026_10_10_040000_create_portal_profile_authorization.php'), base_path('bootstrap/app.php'),
+ resource_path('js/pages/profiles/request.tsx'), resource_path('js/pages/profiles/administration.tsx'), resource_path('js/pages/profiles/audit.tsx'),
+ resource_path('js/components/profile-navigation.tsx'), resource_path('js/components/opportunity-profile-actions.tsx'),
+ resource_path('js/pages/management/opportunities.tsx'), resource_path('js/pages/management/opportunity-draft.tsx'),
+ resource_path('js/types/profile-access.ts'), resource_path('js/lib/profile-json.ts'), resource_path('js/pages/management/shared.tsx'),
+ app_path('Services/PortalProfileInstallation.php'), app_path('Http/Controllers/PortalProfileInstallationController.php'), config_path('portal_profiles.php'), resource_path('js/pages/profiles/installation.tsx')];
+ }
+
+ public function available(): bool
+ {
+ return config('portal.profile_access_enabled') && Schema::hasTable('portal_role_assignments')
+ && Schema::hasTable('portal_superuser_pair') && Schema::hasTable('portal_profile_requests')
+ && Schema::hasTable('portal_security_approvals') && Schema::hasColumn('users', 'portal_access_revision')
+ && Schema::hasColumn('opportunities', 'workflow_context') && Schema::hasColumn('opportunities', 'owner_user_id')
+ && Schema::hasColumn('opportunities', 'organization_id');
+ }
+
+ /** @return list<\stdClass> */
+ public function grants(User $actor, ?string $role = null): array
+ {
+ if (! $this->available() || ! $actor->hasVerifiedEmail()) {
+ return [];
+ }
+
+ return array_values(DB::table('portal_role_assignments')->where('user_id', $actor->id)->whereNull('revoked_at')->where('starts_at', '<=', now())
+ ->where(fn ($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now()))->when($role, fn ($q) => $q->where('role', $role))->get()->all());
+ }
+
+ public function has(User $actor, string $role): bool
+ {
+ return $role === 'superuser' ? $this->superuser($actor) : $this->grants($actor, $role) !== [];
+ }
+
+ public function superuser(User $actor): bool
+ {
+ return $this->available() && $actor->hasVerifiedEmail() && DB::table('portal_superuser_pair')->where('id', 1)
+ ->where(fn ($q) => $q->where('first_user_id', $actor->id)->orWhere('second_user_id', $actor->id))->exists();
+ }
+
+ public function represents(User $actor, ?string $organization): bool
+ {
+ return $organization === null || DB::table('memberships as m')->join('organizations as o', 'o.id', '=', 'm.organization_id')
+ ->where('m.user_id', $actor->id)->where('m.organization_id', $organization)
+ ->whereNull('m.deleted_at')->whereNull('o.deleted_at')->whereIn('m.role', ['admin', 'manager', 'officer'])->exists();
+ }
+
+ public function mfa(User $actor): bool
+ {
+ // Enrollment alone is insufficient: Fortify must have completed MFA in this session.
+ return $actor->two_factor_confirmed_at !== null && $actor->two_factor_secret !== null
+ && session('login.id') === null && session('portal.mfa_actor') === $actor->id
+ && (int) session('portal.mfa_at', 0) >= time() - 900;
+ }
+
+ public function scoped(User $actor, string $role, ?string $organization, string $type): bool
+ {
+ foreach ($this->grants($actor, $role) as $grant) {
+ if (($grant->organization_id === $organization || ($role !== 'promoter' && $grant->organization_id === null))
+ && in_array($type, json_decode($grant->opportunity_types, true, 512, JSON_THROW_ON_ERROR), true)) {
+ return $role !== 'promoter' || $this->represents($actor, $organization);
+ }
+ }
+
+ return false;
+ }
+
+ public function operational(User $actor, string $action, ?int $recordId = null): bool
+ {
+ if ($this->has($actor, 'auditor')) {
+ return false;
+ }
+ if (! $this->superuser($actor)) {
+ return true;
+ }
+
+ return DB::table('portal_security_approvals')->where('kind', 'elevation')->where('subject_user_id', $actor->id)
+ ->whereNotNull('approved_by')->whereNull('consumed_at')->where('expires_at', '>', now())
+ ->whereExists(fn ($q) => $q->selectRaw('1')->from('portal_superuser_pair')
+ ->where(fn ($holders) => $holders->whereColumn('first_user_id', 'portal_security_approvals.approved_by')->orWhereColumn('second_user_id', 'portal_security_approvals.approved_by')))
+ ->where('scope->action', $action)->where('scope->record_id', $recordId)->exists();
+ }
+
+ public function canCreate(User $actor, ?string $organization, string $type): bool
+ {
+ return $this->available() && $this->scoped($actor, 'promoter', $organization, $type) && $this->operational($actor, 'create');
+ }
+
+ public function legacyWriteAllowed(User $actor): bool
+ {
+ // A deliberate v1 assignment cannot use the old allowlist to bypass its scope.
+ if (! $actor->can('manage-portal')) {
+ return false;
+ }
+ if (! Schema::hasTable('portal_role_assignments')) {
+ return true;
+ }
+
+ // Revocation/expiry must not silently restore an older, wider privilege.
+ return ! DB::table('portal_role_assignments')->where('user_id', $actor->id)->exists()
+ && ! DB::table('portal_superuser_pair')->where(fn ($q) => $q->where('first_user_id', $actor->id)->orWhere('second_user_id', $actor->id))->exists()
+ && ! DB::table('portal_security_approvals')->where('kind', 'replacement')->whereNotNull('consumed_at')->where('scope->old_user_id', $actor->id)->exists();
+ }
+
+ public function canView(User $actor, Opportunity $record): bool
+ {
+ if ($record->owner_user_id === null) {
+ return $actor->can('manage-portal');
+ }
+ if (! $this->available() || ! $actor->hasVerifiedEmail()) {
+ return false;
+ }
+ if ($this->has($actor, 'auditor') || $this->superuser($actor)) {
+ return true;
+ }
+ $personal = $record->organization_id !== null || (int) $record->owner_user_id === $actor->id;
+
+ return ($personal && $this->scoped($actor, 'promoter', $record->organization_id, $record->opportunity_category))
+ || $this->scoped($actor, 'validator', $record->organization_id, $record->opportunity_category)
+ || $this->scoped($actor, 'publisher', $record->organization_id, $record->opportunity_category);
+ }
+
+ public function canEdit(User $actor, Opportunity $record, ?string $newType = null): bool
+ {
+ if ($record->owner_user_id === null) {
+ return $this->legacyWriteAllowed($actor);
+ }
+
+ return $this->canView($actor, $record) && ! $record->trashed()
+ && in_array($this->state($record), ['draft', 'needs_information'], true)
+ && $this->scoped($actor, 'promoter', $record->organization_id, $newType ?? $record->opportunity_category)
+ && $this->operational($actor, 'edit', $record->id);
+ }
+
+ public function conflict(User $actor, Opportunity $record): bool
+ {
+ $context = $record->workflow_context ?? [];
+
+ return (int) $record->owner_user_id === $actor->id || in_array($actor->id, $context['contributors'] ?? [], true)
+ || ($record->organization_id !== null && DB::table('memberships')->where('user_id', $actor->id)
+ ->where('organization_id', $record->organization_id)->whereNull('deleted_at')->exists());
+ }
+
+ public function state(Opportunity $record): string
+ {
+ return $record->workflow_context['working_state'] ?? $record->status;
+ }
+
+ public function authorize(User $actor, string $action, Opportunity $record): void
+ {
+ $allowed = $action === 'view' ? $this->canView($actor, $record) : $this->canEdit($actor, $record);
+ if (! $allowed) {
+ $this->audit($actor, 'access_denied', ['record_id' => $record->id, 'action' => $action]);
+ }
+ abort_unless($allowed, 403, 'O perfil, representação, tipo ou estado não autoriza esta operação.');
+ }
+
+ /**
+ * @param Builder $query
+ * @return Builder
+ */
+ public function scope(Builder $query, User $actor): Builder
+ {
+ if ($this->has($actor, 'auditor') || $this->superuser($actor)) {
+ return $query;
+ }
+
+ return $query->where(function ($scope) use ($actor) {
+ $scope->whereRaw('1=0');
+ if ($actor->can('manage-portal')) {
+ $scope->orWhereNull('owner_user_id');
+ }
+ foreach ($this->grants($actor) as $grant) {
+ if ($grant->role === 'promoter' && ! $this->represents($actor, $grant->organization_id)) {
+ continue;
+ }
+ $scope->orWhere(function ($allowed) use ($actor, $grant) {
+ $allowed->whereNotNull('owner_user_id')->whereIn('opportunity_category', json_decode($grant->opportunity_types, true, 512, JSON_THROW_ON_ERROR));
+ if ($grant->organization_id !== null) {
+ $allowed->where('organization_id', $grant->organization_id);
+ } elseif ($grant->role === 'promoter') {
+ $allowed->whereNull('organization_id')->where('owner_user_id', $actor->id);
+ }
+ });
+ }
+ });
+ }
+
+ /** @return array|null */
+ public function navigation(?User $actor): ?array
+ {
+ if (! $actor || ! $this->available() || ! $actor->hasVerifiedEmail()) {
+ return null;
+ }
+ $contexts = [];
+ foreach ($this->grants($actor, 'promoter') as $grant) {
+ if (! $this->represents($actor, $grant->organization_id)) {
+ continue;
+ }
+ foreach (json_decode($grant->opportunity_types, true, 512, JSON_THROW_ON_ERROR) as $type) {
+ if ($this->canCreate($actor, $grant->organization_id, $type)) {
+ $contexts[] = ['organization_id' => $grant->organization_id, 'type' => $type];
+ }
+ }
+ }
+
+ return ['contexts' => $contexts, 'mine' => $contexts ? '/minhas-oportunidades' : null, 'create' => $contexts ? '/minhas-oportunidades/create' : null,
+ 'request' => '/perfil/promotor', 'review' => $this->has($actor, 'validator') || $this->has($actor, 'publisher') || $this->has($actor, 'auditor') || $this->superuser($actor) ? '/minhas-oportunidades' : null,
+ 'audit' => $this->has($actor, 'auditor') || $this->superuser($actor) ? '/perfis/auditoria' : null, 'administration' => $this->superuser($actor) ? '/perfis/gestao' : null];
+ }
+
+ /** @param array $data */
+ public function audit(User $actor, string $action, array $data): void
+ {
+ DB::table('audit_events')->insert(['source_system' => 'portal-profiles-v1', 'entity_type' => 'authorization', 'actor_user_id' => $actor->id,
+ 'action' => $action, 'data_classification' => 'restricted', 'correlation_id' => (string) Str::uuid(),
+ 'after_data' => json_encode([...$data, 'policy_version' => self::VERSION, 'origin_ip' => request()->ip()], JSON_THROW_ON_ERROR)]);
+ }
+
+ public function revokeSessions(User $subject): void
+ {
+ DB::table('users')->where('id', $subject->id)->increment('portal_access_revision');
+ // Invalidate remember-me as well; no password or MFA changes.
+ DB::table('users')->where('id', $subject->id)->update(['remember_token' => null]);
+ if (Schema::hasTable('sessions')) {
+ DB::table('sessions')->where('user_id', $subject->id)->delete();
+ }
+ if (Schema::hasTable('personal_access_tokens')) {
+ DB::table('personal_access_tokens')->where('tokenable_type', User::class)->where('tokenable_id', $subject->id)->delete();
+ }
+ }
+}
diff --git a/app/Services/PortalProfileAdministration.php b/app/Services/PortalProfileAdministration.php
new file mode 100644
index 00000000..e9e4525c
--- /dev/null
+++ b/app/Services/PortalProfileAdministration.php
@@ -0,0 +1,144 @@
+access->superuser($actor) && $this->access->mfa($actor), 403, 'Superutilizador com MFA recente necessário.');
+ abort_if($this->access->has($actor, 'auditor'), 403, 'A restrição de leitura do Auditor prevalece.');
+ }
+
+ /** @param array $input */
+ public function grant(User $actor, array $input): string
+ {
+ $this->administrative($actor);
+ $data = Validator::make($input, ['user_id' => 'required|integer|exists:users,id', 'role' => ['required', Rule::in(['promoter', 'validator', 'publisher', 'auditor'])],
+ 'organization_id' => 'nullable|uuid|exists:organizations,id', 'opportunity_types' => 'required|array|min:1', 'opportunity_types.*' => ['required', Rule::in(OpportunityManagement::CATEGORIES)],
+ 'responsibilities' => 'sometimes|array', 'responsibilities.*' => ['required', Rule::in(['validation_coordinator', 'technical_reviewer', 'legal_reviewer', 'appeal_reviewer', 'publication_coordinator'])],
+ 'expires_at' => 'nullable|date|after:now', 'reason' => 'required|string|min:20|max:1000'])->validate();
+ abort_if((int) $data['user_id'] === $actor->id, 403, 'Não pode aprovar a sua atribuição.');
+ abort_if($data['role'] === 'promoter', 422, 'Promotor exige pedido e revisão documental independente.');
+ $responsibilities = match ($data['role']) {
+ 'validator' => ['validation_coordinator', 'technical_reviewer', 'legal_reviewer', 'appeal_reviewer'],
+ 'publisher' => ['publication_coordinator'],
+ default => [],
+ };
+ abort_unless(array_diff($data['responsibilities'] ?? [], $responsibilities) === [], 422, 'Responsabilidade incompatível com o papel.');
+ $subject = User::whereKey($data['user_id'])->firstOrFail();
+ abort_unless($subject->hasVerifiedEmail(), 422);
+ if (in_array($data['role'], ['validator', 'publisher'], true)) {
+ abort_unless($subject->two_factor_secret !== null && $subject->two_factor_confirmed_at !== null, 422, 'Configure e confirme MFA antes de atribuir este papel.');
+ }
+
+ return DB::transaction(function () use ($actor, $data) {
+ $id = (string) Str::uuid();
+ $this->insertGrant($id, $actor, $data);
+ $this->access->audit($actor, 'role_granted', ['assignment_id' => $id, 'subject_user_id' => $data['user_id'], 'role' => $data['role'], 'reason' => $data['reason']]);
+
+ return $id;
+ });
+ }
+
+ /** @param array $data */
+ public function insertGrant(string $id, User $approver, array $data): void
+ {
+ DB::table('portal_role_assignments')->insert(['id' => $id, 'user_id' => $data['user_id'], 'role' => $data['role'], 'organization_id' => $data['organization_id'] ?? null,
+ 'opportunity_types' => json_encode(array_values(array_unique($data['opportunity_types'])), JSON_THROW_ON_ERROR), 'responsibilities' => json_encode($data['responsibilities'] ?? [], JSON_THROW_ON_ERROR),
+ 'source' => $data['source'] ?? 'independent-administration', 'request_id' => $data['request_id'] ?? null, 'approved_by' => $approver->id,
+ 'starts_at' => now(), 'expires_at' => $data['expires_at'] ?? null, 'created_at' => now(), 'updated_at' => now()]);
+ }
+
+ public function revoke(User $actor, string $id, string $reason): void
+ {
+ $this->administrative($actor);
+ Validator::make(['reason' => $reason], ['reason' => 'required|string|min:20|max:1000'])->validate();
+ DB::transaction(function () use ($actor, $id, $reason) {
+ $row = DB::table('portal_role_assignments')->where('id', $id)->lockForUpdate()->first();
+ abort_unless($row !== null, 404);
+ if ($row->revoked_at !== null) {
+ return;
+ }
+ DB::table('portal_role_assignments')->where('id', $id)->update(['revoked_at' => now(), 'updated_at' => now()]);
+ $this->access->revokeSessions(User::whereKey($row->user_id)->firstOrFail());
+ $this->access->audit($actor, 'role_revoked', ['assignment_id' => $id, 'subject_user_id' => $row->user_id, 'reason' => $reason]);
+ });
+ }
+
+ /** @param array $input */
+ public function request(User $actor, array $input): string
+ {
+ abort_unless($this->access->available() && $actor->hasVerifiedEmail(), 403);
+ $data = Validator::make($input, ['creation_key' => 'required|uuid', 'representation_type' => 'required|in:individual,company,public_entity,association,partner',
+ 'organization_id' => 'nullable|uuid|exists:organizations,id', 'opportunity_types' => 'required|array|min:1', 'opportunity_types.*' => ['required', Rule::in(OpportunityManagement::CATEGORIES)],
+ 'document_ids' => 'required|array|min:1', 'document_ids.*' => 'required|uuid|exists:documents,id', 'reason' => 'required|string|min:20|max:1000'])->validate();
+ $organization = $data['organization_id'] ?? null;
+ abort_unless(($data['representation_type'] === 'individual') === ($organization === null), 422, 'Pessoa singular usa âmbito próprio; as entidades exigem organização.');
+ abort_unless($this->access->represents($actor, $organization), 403, 'Representação ativa de escrita necessária.');
+ foreach ($data['document_ids'] as $id) {
+ abort_unless(DB::table('documents')->where('id', $id)->where('uploaded_by', $actor->id)->whereNull('deleted_at')->where('status', 'active')
+ ->where('malware_scan_status', 'clean')->whereColumn('sha256', 'malware_scanned_sha256')->exists(), 422, 'Comprovativo próprio, íntegro e analisado necessário.');
+ }
+
+ return DB::transaction(function () use ($actor, $data, $organization) {
+ DB::select('SELECT pg_advisory_xact_lock(101026, 40000)');
+ $existing = DB::table('portal_profile_requests')->where('creation_key', $data['creation_key'])->first();
+ if ($existing) {
+ abort_unless((int) $existing->user_id === $actor->id, 403);
+ abort_unless($existing->organization_id === $organization && $existing->representation_type === $data['representation_type']
+ && json_decode($existing->opportunity_types, true) === $data['opportunity_types'] && json_decode($existing->document_ids, true) === $data['document_ids'] && $existing->reason === $data['reason'], 409, 'Chave já usada com outro pedido.');
+
+ return $existing->id;
+ }
+ $id = (string) Str::uuid();
+ DB::table('portal_profile_requests')->insert(['id' => $id, 'user_id' => $actor->id, 'organization_id' => $organization,
+ 'representation_type' => $data['representation_type'], 'opportunity_types' => json_encode($data['opportunity_types'], JSON_THROW_ON_ERROR),
+ 'document_ids' => json_encode($data['document_ids'], JSON_THROW_ON_ERROR), 'reason' => $data['reason'], 'creation_key' => $data['creation_key'], 'created_at' => now(), 'updated_at' => now()]);
+ $this->access->audit($actor, 'promoter_requested', ['request_id' => $id, 'types' => $data['opportunity_types']]);
+
+ return $id;
+ });
+ }
+
+ /** @param array $input */
+ public function decide(User $actor, string $id, array $input): void
+ {
+ $this->administrative($actor);
+ $data = Validator::make($input, ['version' => 'required|integer|min:1', 'decision' => 'required|in:approved,rejected', 'reason' => 'required|string|min:20|max:1000',
+ 'verified_identity' => 'required|boolean|accepted_if:decision,approved', 'verified_representation' => 'required|boolean|accepted_if:decision,approved', 'verified_documents' => 'required|boolean|accepted_if:decision,approved',
+ 'approved_types' => 'present|array', 'approved_types.*' => ['required', Rule::in(OpportunityManagement::CATEGORIES)], 'expires_at' => 'nullable|date|after:now'])->validate();
+ DB::transaction(function () use ($actor, $id, $data) {
+ $row = DB::table('portal_profile_requests')->where('id', $id)->lockForUpdate()->first();
+ abort_unless($row !== null, 404);
+ abort_if((int) $row->user_id === $actor->id, 403, 'Não pode aprovar o seu pedido.');
+ abort_unless($row->status === 'pending' && (int) $row->version === (int) $data['version'], 409);
+ $requested = json_decode($row->opportunity_types, true, 512, JSON_THROW_ON_ERROR);
+ abort_unless(array_diff($data['approved_types'], $requested) === [], 422, 'Só podem ser aprovados tipos pedidos.');
+ $subject = User::whereKey($row->user_id)->firstOrFail();
+ if ($data['decision'] === 'approved') {
+ abort_unless($this->access->represents($subject, $row->organization_id), 403, 'Representação entretanto revogada.');
+ foreach (json_decode($row->document_ids, true) as $document) {
+ abort_unless(DB::table('documents')->where('id', $document)->where('uploaded_by', $subject->id)->whereNull('deleted_at')->where('status', 'active')
+ ->where('malware_scan_status', 'clean')->whereColumn('sha256', 'malware_scanned_sha256')->exists(), 422, 'Comprovativo entretanto indisponível.');
+ }
+ }
+ if ($data['decision'] === 'approved') {
+ abort_unless($data['approved_types'] !== [], 422, 'Escolha ao menos um tipo.');
+ $this->insertGrant((string) Str::uuid(), $actor, ['user_id' => $subject->id, 'role' => 'promoter', 'organization_id' => $row->organization_id,
+ 'opportunity_types' => $data['approved_types'], 'request_id' => $id, 'source' => 'documented-promoter-request', 'expires_at' => $data['expires_at'] ?? null]);
+ }
+ DB::table('portal_profile_requests')->where('id', $id)->update(['status' => $data['decision'], 'version' => $row->version + 1, 'decided_by' => $actor->id,
+ 'decision_reason' => $data['reason'], 'decided_at' => now(), 'updated_at' => now()]);
+ $this->access->audit($actor, 'promoter_request_decided', ['request_id' => $id, 'decision' => $data['decision'], 'approved_types' => $data['approved_types'], 'reason' => $data['reason'], 'checks' => array_intersect_key($data, array_flip(['verified_identity', 'verified_representation', 'verified_documents']))]);
+ });
+ }
+}
diff --git a/app/Services/PortalProfileInstallation.php b/app/Services/PortalProfileInstallation.php
new file mode 100644
index 00000000..1dc82459
--- /dev/null
+++ b/app/Services/PortalProfileInstallation.php
@@ -0,0 +1,166 @@
+ hash_file('sha256', $path), array_unique($files)), JSON_THROW_ON_ERROR));
+ }
+
+ public function authorize(User $actor, bool $write = false): void
+ {
+ abort_unless($actor->hasVerifiedEmail(), 403);
+ if (Schema::hasTable('portal_role_assignments')) {
+ abort_if(DB::table('portal_role_assignments')->where('user_id', $actor->id)->where('role', 'auditor')->whereNull('revoked_at')
+ ->where('starts_at', '<=', now())->where(fn ($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now()))->exists(), 403, 'A restrição do Auditor prevalece.');
+ }
+ $pair = Schema::hasTable('portal_superuser_pair') ? DB::table('portal_superuser_pair')->where('id', 1)->first() : null;
+ abort_unless($pair ? in_array($actor->id, [(int) $pair->first_user_id, (int) $pair->second_user_id], true) : $actor->can('manage-portal'), 403, 'Gestor de instalação ou titular da dupla necessário.');
+ if ($write) {
+ abort_unless($this->access->mfa($actor), 403, 'Conclua MFA nesta sessão; configuração de MFA isoladamente não autoriza a operação.');
+ }
+ }
+
+ /** @return array */
+ public function preview(User $actor): array
+ {
+ $this->authorize($actor);
+ $identity = DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
+ $ledger = DB::table('migrations')->where('migration', self::MIGRATION)->exists();
+ $schema = [];
+ foreach (self::TABLES as $table) {
+ $schema[$table] = Schema::hasTable($table);
+ }
+ foreach (['users' => ['portal_access_revision'], 'opportunities' => ['owner_user_id', 'organization_id', 'workflow_context']] as $table => $columns) {
+ foreach ($columns as $column) {
+ $schema[$table.'.'.$column] = Schema::hasColumn($table, $column);
+ }
+ }
+ $all = ! in_array(false, $schema, true);
+ $none = ! in_array(true, $schema, true);
+ $consistent = ($ledger && $all) || (! $ledger && $none);
+ $installed = $ledger && $all;
+ $dependencies = [
+ 'management_020000' => DB::table('migrations')->where('migration', '2026_10_09_020000_extend_opportunity_management')->exists() && Schema::hasColumn('opportunities', 'management_draft'),
+ 'resources_030000' => DB::table('migrations')->where('migration', '2026_10_09_030000_extend_opportunity_resources')->exists()
+ && Schema::hasTable('opportunity_documents') && Schema::hasTable('opportunity_images') && Schema::hasTable('opportunity_location_drafts') && Schema::hasColumn('documents', 'storage_encryption'),
+ 'existing_identity_organization_audit' => Schema::hasTable('users') && Schema::hasTable('organizations') && Schema::hasTable('memberships') && Schema::hasTable('audit_events'),
+ ];
+ $code = $this->fingerprint();
+ $proofPath = config('portal_profiles.proof_directory').'/readiness.json';
+ $proofBytes = is_file($proofPath) ? file_get_contents($proofPath) : false;
+ $proof = is_string($proofBytes) ? json_decode($proofBytes, true) : [];
+ $proof = is_array($proof) ? $proof : [];
+ $fresh = isset($proof['verified_at']) && strtotime($proof['verified_at']) >= time() - 86400;
+ $evidence = $fresh && ($proof['code_hash'] ?? '') === $code && ($proof['target']['database'] ?? '') === $identity->database
+ && (int) ($proof['target']['port'] ?? 0) === (int) $identity->port && ($proof['restore_verified'] ?? false) && ($proof['files_verified'] ?? false)
+ && ($proof['compatibility_verified'] ?? false) && ($proof['qa_passed'] ?? false)
+ && is_file($proof['dump_path'] ?? '') && hash_file('sha256', $proof['dump_path']) === ($proof['dump_sha256'] ?? null)
+ && is_file($proof['files_path'] ?? '') && hash_file('sha256', $proof['files_path']) === ($proof['files_sha256'] ?? null);
+ $ready = $consistent && ! in_array(false, $dependencies, true) && $evidence;
+ $pair = $installed ? DB::table('portal_superuser_pair')->where('id', 1)->first() : null;
+ $bootstrap = ['initialized' => $pair !== null, 'holders' => $pair ? [(int) $pair->first_user_id, (int) $pair->second_user_id] : [], 'version' => $pair?->version,
+ 'rule' => 'Escolher explicitamente duas contas confirmadas com MFA; um terceiro gestor com MFA aprova. Sem escolha automática, sem alteração de papéis legados.'];
+ $plan = ['target' => $identity, 'code_hash' => $code, 'installed' => $installed, 'consistent' => $consistent, 'ledger' => $ledger, 'schema' => $schema,
+ 'dependencies' => $dependencies, 'ready' => $ready, 'backupDate' => $proof['verified_at'] ?? null, 'bootstrap' => $bootstrap,
+ 'path_190000_installed' => DB::table('migrations')->where('migration', '2026_10_09_190000_prepare_investor_path')->exists(),
+ 'migration' => self::MIGRATION, 'changes' => ['Quatro tabelas, uma coluna em users e três em opportunities; zero contas e zero atribuições automáticas.',
+ '030000 precede esta ação; 190000 continua etapa posterior do percurso, sem dependência DDL desta migração.', 'Nenhuma flag ativada, dado publicado, titular escolhido ou privilégio legado removido.'],
+ 'rollback' => 'DDL e ledger são atómicos em PostgreSQL. Se vazio, down deve remover todas as colunas adicionadas; se houver uso/histórico, preservar e restaurar backup verificado, sem rollback destrutivo.'];
+ $plan['hash'] = hash('sha256', json_encode($plan, JSON_THROW_ON_ERROR));
+
+ return $plan;
+ }
+
+ /** @param array $input
+ * @return array */
+ public function apply(User $actor, array $input): array
+ {
+ $this->authorize($actor, true);
+ $data = Validator::make($input, ['hash' => 'required|string|size:64', 'confirm' => 'required|accepted', 'idempotency_key' => 'required|uuid', 'reason' => 'required|string|min:20|max:1000'])->validate();
+
+ return $this->receipt($actor, 'install', $data, function () use ($actor, $data) {
+ $p = $this->preview($actor);
+ abort_unless(hash_equals($p['hash'], $data['hash']), 409, 'Plano alterado; consulte a pré-visualização.');
+ abort_unless($p['consistent'], 409, 'Ledger/schema incoerentes; recuperar antes de instalar.');
+ if ($p['installed']) {
+ return ['installed' => true, 'changed' => false, 'migration' => self::MIGRATION, 'bootstrap_required' => ! $p['bootstrap']['initialized'], 'flags_changed' => false];
+ }
+ abort_unless($p['ready'], 422, 'Dependências e provas atuais de backup/restauro/QA são necessárias.');
+ config(['portal_profiles.authenticated_installation' => true]);
+ try {
+ abort_unless(Artisan::call('migrate', ['--path' => 'database/migrations/'.self::MIGRATION.'.php', '--force' => true]) === 0, 500, 'A instalação falhou; a transação é revertida.');
+ } finally {
+ config(['portal_profiles.authenticated_installation' => false]);
+ }
+ $after = $this->preview($actor);
+ abort_unless($after['installed'] && $after['consistent'], 500, 'Verificação pós-instalação falhou; reverter transação.');
+
+ return ['installed' => true, 'changed' => true, 'migration' => self::MIGRATION, 'bootstrap_required' => true, 'flags_changed' => false];
+ });
+ }
+
+ /** @param array $input
+ * @return array */
+ public function bootstrap(User $actor, array $input): array
+ {
+ $this->authorize($actor, true);
+ $data = Validator::make($input, ['hash' => 'required|string|size:64', 'confirm' => 'required|accepted', 'idempotency_key' => 'required|uuid',
+ 'first_user_id' => 'required|integer|exists:users,id', 'second_user_id' => 'required|integer|different:first_user_id|exists:users,id', 'reason' => 'required|string|min:20|max:1000'])->validate();
+
+ return $this->receipt($actor, 'bootstrap', $data, function () use ($actor, $data) {
+ $p = $this->preview($actor);
+ abort_unless(hash_equals($p['hash'], $data['hash']), 409, 'Plano alterado.');
+ abort_unless($p['installed'] && ! $p['bootstrap']['initialized'], 409, 'Inicialização exige schema instalado e dupla ainda não designada. Use substituição para uma dupla existente.');
+ config(['portal_profiles.bootstrap_authorized' => true]);
+ try {
+ app(PortalSuperusers::class)->initialize(User::query()->whereKey($data['first_user_id'])->firstOrFail(), User::query()->whereKey($data['second_user_id'])->firstOrFail(), $actor);
+ } finally {
+ config(['portal_profiles.bootstrap_authorized' => false]);
+ }
+
+ return ['initialized' => true, 'holders' => [$data['first_user_id'], $data['second_user_id']], 'version' => 1, 'flags_changed' => false];
+ });
+ }
+
+ /** @param array $data
+ * @param callable():array $operation
+ * @return array */
+ private function receipt(User $actor, string $scope, array $data, callable $operation): array
+ {
+ return DB::transaction(function () use ($actor, $scope, $data, $operation) {
+ DB::select('SELECT pg_advisory_xact_lock(101026, 40000)');
+ $requestHash = hash('sha256', json_encode($data, JSON_THROW_ON_ERROR));
+ $previous = DB::table('audit_events')->where('source_system', 'portal-profile-installation')->where('action', $scope)->where('actor_user_id', $actor->id)->where('correlation_id', $data['idempotency_key'])->first();
+ if ($previous) {
+ $receipt = json_decode($previous->after_data, true, 512, JSON_THROW_ON_ERROR);
+ abort_unless(hash_equals($receipt['request_hash'], $requestHash), 409, 'Chave de repetição reutilizada com outro conteúdo.');
+
+ return $receipt['result'];
+ }
+ $result = $operation();
+ DB::table('audit_events')->insert(['source_system' => 'portal-profile-installation', 'entity_type' => 'installation', 'actor_user_id' => $actor->id, 'action' => $scope,
+ 'correlation_id' => $data['idempotency_key'], 'data_classification' => 'restricted', 'after_data' => json_encode(['request_hash' => $requestHash, 'reason' => $data['reason'], 'result' => $result, 'code_hash' => $this->fingerprint()], JSON_THROW_ON_ERROR)]);
+
+ return $result;
+ });
+ }
+}
diff --git a/app/Services/PortalSuperusers.php b/app/Services/PortalSuperusers.php
new file mode 100644
index 00000000..178482a7
--- /dev/null
+++ b/app/Services/PortalSuperusers.php
@@ -0,0 +1,115 @@
+id, $second->id, $approver->id])) === 3, 422);
+ foreach ([$first, $second, $approver] as $user) {
+ abort_unless($user->hasVerifiedEmail() && $user->two_factor_secret && $user->two_factor_confirmed_at, 422, 'Contas confirmadas com MFA necessário.');
+ try {
+ $secret = Crypt::decryptString($user->two_factor_secret);
+ } catch (DecryptException) {
+ abort(422, 'Configuração MFA incompatível com este ambiente. Recuperar a conta pelo procedimento existente antes da inicialização.');
+ }
+ abort_unless(strlen($secret) >= 16 && preg_match('/^[A-Z2-7]+=*$/', $secret), 422, 'Configuração MFA inválida.');
+ abort_if(DB::table('portal_role_assignments')->where('user_id', $user->id)->where('role', 'auditor')->whereNull('revoked_at')
+ ->where('starts_at', '<=', now())->where(fn ($q) => $q->whereNull('expires_at')->orWhere('expires_at', '>', now()))->exists(), 422, 'A restrição do Auditor impede a designação de titular nesta cerimónia.');
+ }
+ abort_unless($this->access->mfa($approver), 403);
+ DB::transaction(function () use ($first, $second, $approver) {
+ DB::select('SELECT pg_advisory_xact_lock(101026, 40001)');
+ $existing = DB::table('portal_superuser_pair')->where('id', 1)->first();
+ if ($existing) {
+ abort_unless((int) $existing->first_user_id === $first->id && (int) $existing->second_user_id === $second->id, 409, 'Inicialização já realizada. Use substituição atómica.');
+
+ return;
+ }
+ DB::table('portal_superuser_pair')->insert(['id' => 1, 'first_user_id' => $first->id, 'second_user_id' => $second->id, 'approved_by' => $approver->id, 'created_at' => now(), 'updated_at' => now()]);
+ $this->access->audit($approver, 'superuser_pair_initialized', ['holders' => [$first->id, $second->id], 'version' => 1]);
+ });
+ }
+
+ public function requestReplacement(User $actor, int $oldId, int $newId, string $reason): string
+ {
+ $this->administration->administrative($actor);
+ abort_unless(mb_strlen($reason) >= 20 && mb_strlen($reason) <= 1000 && $oldId !== $newId, 422);
+
+ return DB::transaction(function () use ($actor, $oldId, $newId, $reason) {
+ $pair = DB::table('portal_superuser_pair')->where('id', 1)->lockForUpdate()->first();
+ $holders = [(int) $pair->first_user_id, (int) $pair->second_user_id];
+ abort_unless(in_array($oldId, $holders, true) && ! in_array($newId, $holders, true), 422);
+ $candidate = User::findOrFail($newId);
+ abort_unless($candidate->hasVerifiedEmail() && $candidate->two_factor_secret && $candidate->two_factor_confirmed_at, 422);
+ $id = (string) Str::uuid();
+ DB::table('portal_security_approvals')->insert(['id' => $id, 'kind' => 'replacement', 'requested_by' => $actor->id, 'subject_user_id' => $newId,
+ 'scope' => json_encode(['old_user_id' => $oldId, 'pair_version' => (int) $pair->version], JSON_THROW_ON_ERROR), 'reason' => $reason,
+ 'expires_at' => now()->addMinutes(15), 'created_at' => now(), 'updated_at' => now()]);
+ $this->access->audit($actor, 'superuser_replacement_requested', ['approval_id' => $id, 'old_user_id' => $oldId, 'new_user_id' => $newId]);
+
+ return $id;
+ });
+ }
+
+ public function approve(User $actor, string $id): void
+ {
+ $this->administration->administrative($actor);
+ DB::transaction(function () use ($actor, $id) {
+ $row = DB::table('portal_security_approvals')->where('id', $id)->lockForUpdate()->first();
+ abort_unless($row !== null, 404);
+ abort_if((int) $row->requested_by === $actor->id || (int) $row->subject_user_id === $actor->id, 403, 'Aprovação independente necessária.');
+ abort_unless($row->consumed_at === null && strtotime($row->expires_at) > time() && $row->approved_by === null, 409);
+ DB::table('portal_security_approvals')->where('id', $id)->update(['approved_by' => $actor->id, 'updated_at' => now()]);
+ $this->access->audit($actor, 'security_operation_approved', ['approval_id' => $id, 'kind' => $row->kind]);
+ });
+ }
+
+ public function applyReplacement(User $actor, string $id): void
+ {
+ $this->administration->administrative($actor);
+ DB::transaction(function () use ($actor, $id) {
+ DB::select('SELECT pg_advisory_xact_lock(101026, 40001)');
+ $pair = DB::table('portal_superuser_pair')->where('id', 1)->lockForUpdate()->first();
+ $row = DB::table('portal_security_approvals')->where('id', $id)->lockForUpdate()->first();
+ abort_unless($row && $row->kind === 'replacement' && (int) $row->requested_by === $actor->id, 403);
+ abort_unless($row->approved_by !== null && $row->consumed_at === null && strtotime($row->expires_at) > time(), 409);
+ $scope = json_decode($row->scope, true, 512, JSON_THROW_ON_ERROR);
+ $holders = [(int) $pair->first_user_id, (int) $pair->second_user_id];
+ abort_unless((int) $pair->version === $scope['pair_version'] && in_array((int) $row->approved_by, $holders, true)
+ && in_array($scope['old_user_id'], $holders, true) && ! in_array((int) $row->subject_user_id, $holders, true), 409, 'Dupla ou aprovação mudou.');
+ $candidate = User::whereKey($row->subject_user_id)->firstOrFail();
+ abort_unless($candidate->hasVerifiedEmail() && $candidate->two_factor_secret && $candidate->two_factor_confirmed_at, 422);
+ $column = (int) $pair->first_user_id === $scope['old_user_id'] ? 'first_user_id' : 'second_user_id';
+ // A single UPDATE preserves two distinct holders at every observable state.
+ DB::table('portal_superuser_pair')->where('id', 1)->update([$column => $candidate->id, 'version' => $pair->version + 1, 'approved_by' => $row->approved_by, 'updated_at' => now()]);
+ DB::table('portal_security_approvals')->where('id', $id)->update(['consumed_at' => now(), 'updated_at' => now()]);
+ $this->access->revokeSessions(User::findOrFail($scope['old_user_id']));
+ $this->access->audit($actor, 'superuser_replaced', ['approval_id' => $id, 'before' => $holders, 'after' => DB::table('portal_superuser_pair')->where('id', 1)->first(), 'alert' => 'Substituição de titular: verificar acessos e recuperação.']);
+ });
+ }
+
+ public function requestElevation(User $actor, string $action, ?int $recordId, string $reason): string
+ {
+ $this->administration->administrative($actor);
+ abort_unless(in_array($action, ['create', 'edit', 'validate', 'publish', 'archive'], true) && mb_strlen($reason) >= 20 && mb_strlen($reason) <= 1000, 422);
+ $id = (string) Str::uuid();
+ DB::table('portal_security_approvals')->insert(['id' => $id, 'kind' => 'elevation', 'requested_by' => $actor->id, 'subject_user_id' => $actor->id,
+ 'scope' => json_encode(['action' => $action, 'record_id' => $recordId], JSON_THROW_ON_ERROR), 'reason' => $reason,
+ 'expires_at' => now()->addMinutes(15), 'created_at' => now(), 'updated_at' => now()]);
+ $this->access->audit($actor, 'elevation_requested', ['approval_id' => $id, 'action' => $action, 'record_id' => $recordId, 'reason' => $reason]);
+
+ return $id;
+ }
+}
diff --git a/app/Services/TerritoryGeometryImport.php b/app/Services/TerritoryGeometryImport.php
index 3d51c053..025cae82 100644
--- a/app/Services/TerritoryGeometryImport.php
+++ b/app/Services/TerritoryGeometryImport.php
@@ -13,7 +13,7 @@ class TerritoryGeometryImport
{
public function fingerprint(): string
{
- return hash('sha256', implode('', array_map(fn ($f) => hash_file('sha256', $f), [__FILE__, config_path('geometry-import.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), base_path('routes/web.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
+ return hash('sha256', implode('', array_map(fn ($f) => hash_file('sha256', $f), [__FILE__, config_path('geometry-import.php'), config_path('geometry-correspondences.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), base_path('routes/web.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
base_path('bootstrap/app.php'), app_path('Providers/FortifyServiceProvider.php'), config_path('fortify.php'),
resource_path('js/pages/auth/login.tsx'), resource_path('js/pages/auth/two-factor-challenge.tsx')])));
}
@@ -32,7 +32,7 @@ class TerritoryGeometryImport
return;
}
$file = storage_path('app/private/investmoz-v2/geometry-import-activation-proof.json');
- $p = is_file($file) ? json_decode(file_get_contents($file), true) : [];
+ $p = is_file($file) ? json_decode($this->readFile($file), true) : [];
abort_unless(($p['restore_verified'] ?? false) && ($p['qa_passed'] ?? false) && ($p['ui_passed'] ?? false)
&& ($p['code_hash'] ?? '') === $this->fingerprint() && ($p['target']['database'] ?? '') === $target->database
&& (int) ($p['target']['port'] ?? 0) === (int) $target->port && strtotime($p['verified_at'] ?? '') >= time() - 86400
@@ -40,6 +40,7 @@ class TerritoryGeometryImport
&& ($p['files_verified'] ?? false) && is_file($p['files_path'] ?? '') && hash_file('sha256', $p['files_path']) === ($p['files_sha256'] ?? null), 422, 'Backup/restauro e provas desta revisão e alvo necessários; preparação não autoriza ativação.');
}
+ /** @return array */
public function preview(User $actor, int $level): array
{
$this->guard($actor);
@@ -48,12 +49,15 @@ class TerritoryGeometryImport
$file = $directory.'/moz-adm'.$level.'-ine-20190607.geojson';
$metadata = $directory.'/moz-adm'.$level.'-ine-metadata.html';
abort_unless(is_file($file) && is_file($metadata), 422, 'Exemplar privado indisponível.');
- $text = file_get_contents($metadata);
+ $text = $this->readFile($metadata);
abort_unless(str_contains($text, 'Mozambique INE - Instituto Nacional de Estatistica') && str_contains($text, '2019-06-07'), 422, 'Metadados do exemplar divergentes.');
$sourceHash = hash_file('sha256', $file);
- $source = json_decode(file_get_contents($file), true, 512, JSON_THROW_ON_ERROR);
+ $source = json_decode($this->readFile($file), true, 512, JSON_THROW_ON_ERROR);
abort_unless(($source['type'] ?? '') === 'FeatureCollection' && count($source['features'] ?? []) === [1 => 11, 2 => 159, 3 => 411][$level] && ! ($source['exceededTransferLimit'] ?? false), 422, 'Exemplar incompleto.');
- $locations = DB::table('geo_locations')->where('location_type', [1 => 'province', 2 => 'district', 3 => 'admin_post'][$level])->whereNull('deleted_at')->get(['id', 'name', 'parent_id']);
+ $locations = DB::table('geo_locations')->where('location_type', [1 => 'province', 2 => 'district', 3 => 'admin_post'][$level])->whereNull('deleted_at')->get(['id', 'name', 'parent_id', 'source_system', 'source_code', 'external_id']);
+ $crosswalk = config('geometry-correspondences');
+ $correspondences = $crosswalk['rows'][$level] ?? [];
+ abort_if($correspondences && (($crosswalk['edition'] ?? null) !== '2019-06-07' || ($crosswalk['source_sha256'][$level] ?? null) !== $sourceHash), 422, 'Correspondências não pertencem a este exemplar; nenhuma aproximação aplicada.');
$normalize = fn ($n) => strtolower(trim(Str::ascii($n)));
$countryNames = array_map($normalize, [$source['features'][0]['properties']['ADM0_PT'], $source['features'][0]['properties']['ADM0_EN']]);
$countries = DB::table('geo_locations')->where('location_type', 'country')->whereNull('deleted_at')->get(['id', 'name'])->filter(fn ($c) => in_array($normalize($c->name), $countryNames, true))->values();
@@ -66,9 +70,19 @@ class TerritoryGeometryImport
$external = '2019-06-07:adm'.$level.':'.$p['ADM'.$level.'_PCODE'];
$parent = $level > 1 ? DB::table('geo_geometries')->where('source_system', 'ine-cod-ab')->where('external_id', '2019-06-07:adm'.($level - 1).':'.$p['ADM'.($level - 1).'_PCODE'])->where('properties->source_sha256', $parentSourceHash)->whereNull('deleted_at')->value('geo_location_id') : $countryId;
$matches = $locations->filter(fn ($l) => $normalize($l->name) === $normalize($p['ADM'.$level.'_PT']) && $parent && $l->parent_id === $parent)->values();
+ $correspondence = $correspondences[$p['ADM'.$level.'_PCODE']] ?? null;
+ $matchBasis = 'unique_exact_name_and_matched_parent_after_case_and_diacritics';
+ if ($correspondence) {
+ abort_unless($correspondence['source_name'] === $p['ADM'.$level.'_PT'] && $correspondence['parent_source_code'] === $p['ADM'.($level - 1).'_PCODE'], 422, 'Nome/pai do exemplar divergente da correspondência explícita.');
+ $matches = $locations->filter(fn ($l) => $parent && $l->parent_id === $parent
+ && $normalize($l->name) === $normalize($correspondence['target_name']) && $l->source_code === $correspondence['target_source_code']
+ && $l->source_system === $crosswalk['catalogue_source_system'] && str_starts_with($l->external_id ?? '', $crosswalk['catalogue_sha256'].':'))->values();
+ $matchBasis = 'explicit_versioned_correspondence';
+ }
$row = ['external_id' => $external, 'name' => $p['ADM'.$level.'_PT'], 'parent_name' => $level > 1 ? $p['ADM'.($level - 1).'_PT'] : null,
'parent_code' => $level > 1 ? $p['ADM'.($level - 1).'_PCODE'] : null, 'candidates' => $matches->all(), 'location_id' => count($matches) === 1 ? $matches[0]->id : null,
- 'status' => count($matches) === 1 ? 'insert' : (! $parent ? 'parent_unresolved' : 'name_unresolved')];
+ 'status' => count($matches) === 1 ? 'insert' : (count($matches) > 1 ? ($correspondence ? 'correspondence_conflict' : 'ambiguous_name') : (! $parent ? 'parent_unresolved' : 'name_unresolved')),
+ 'match_basis' => $matchBasis, 'correspondence' => $correspondence, 'correspondence_version' => $correspondence ? $crosswalk['version'] : null];
if ($row['location_id']) {
$geometry = json_encode($feature['geometry'], JSON_THROW_ON_ERROR);
$valid = DB::selectOne('SELECT ST_IsValid(g) AND NOT ST_IsEmpty(g) AND ST_NDims(g)=2 AND GeometryType(g) IN (\'POLYGON\',\'MULTIPOLYGON\') AND ST_XMin(Box3D(g))>=-180 AND ST_XMax(Box3D(g))<=180 AND ST_YMin(Box3D(g))>=-90 AND ST_YMax(Box3D(g))<=90 AS valid FROM (SELECT ST_SetSRID(ST_GeomFromGeoJSON(?),4326) g) q', [$geometry]);
@@ -91,7 +105,7 @@ class TerritoryGeometryImport
$rows[] = $row;
}
$scanFile = $directory.'/geometry-source-scans.json';
- $scans = is_file($scanFile) ? json_decode(file_get_contents($scanFile), true) : [];
+ $scans = is_file($scanFile) ? json_decode($this->readFile($scanFile), true) : [];
$scan = null;
foreach ($scans['files'] ?? [] as $s) {
if ($s['file'] === basename($file) && $s['sha256'] === $sourceHash) {
@@ -101,6 +115,7 @@ class TerritoryGeometryImport
$scanReady = ($scan['result'] ?? '') === 'clean' && ($scan['engine'] ?? '') === 'ClamAV' && strtotime($scans['captured_at'] ?? '') >= time() - config('geometry-import.scan_max_age_seconds');
$target = DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
$plan = ['level' => $level, 'target' => $target, 'edition' => '2019-06-07', 'source_sha256' => $sourceHash, 'metadata_sha256' => hash_file('sha256', $metadata), 'code_hash' => $this->fingerprint(),
+ 'correspondence_version' => $crosswalk['version'], 'correspondence_sha256' => hash('sha256', json_encode($crosswalk, JSON_THROW_ON_ERROR)),
'expected' => count($rows), 'resolved' => count(array_filter($rows, fn ($r) => in_array($r['status'], ['insert', 'reuse'], true))), 'rows' => $rows, 'scan_ready' => $scanReady, 'scan' => $scan, 'scan_at' => $scans['captured_at'] ?? null, 'published' => false];
$plan['pending'] = $plan['expected'] - $plan['resolved'];
$plan['hash'] = hash_hmac('sha256', json_encode([$actor->id, $plan], JSON_THROW_ON_ERROR), config('app.key'));
@@ -108,6 +123,9 @@ class TerritoryGeometryImport
return $plan;
}
+ /** @param array $input
+ * @return array
+ */
public function apply(User $actor, array $input): array
{
$this->guard($actor, true);
@@ -118,12 +136,14 @@ class TerritoryGeometryImport
abort_unless(hash_equals($plan['hash'], $data['hash']), 409, 'Correspondências, fonte ou estado alterados; repita a pré-visualização.');
abort_unless($plan['scan_ready'], 423, 'Scan limpo atual ligado ao original necessário.');
abort_if(count(array_filter($plan['rows'], fn ($r) => str_contains($r['status'], 'conflict') || $r['status'] === 'invalid_geometry')) > 0, 409, 'Conflito de identidade/geometria: nenhuma escrita aplicada.');
- $bytes = file_get_contents(config('geometry-import.directory').'/moz-adm'.$data['level'].'-ine-20190607.geojson');
+ $bytes = $this->readFile(config('geometry-import.directory').'/moz-adm'.$data['level'].'-ine-20190607.geojson');
abort_unless(hash('sha256', $bytes) === $plan['source_sha256'], 409);
$source = json_decode($bytes, true, 512, JSON_THROW_ON_ERROR);
$metadata = config('geometry-import.directory').'/moz-adm'.$data['level'].'-ine-metadata.html';
- $metadataScan = app(MalwareScanner::class)->scan($metadata, filesize($metadata), storage_path('app/private'));
- abort_unless(($metadataScan['result'] ?? '') === 'clean', 423, 'Scan dos metadados do exemplar pendente ou inconclusivo.');
+ $metadataSize = filesize($metadata);
+ abort_unless(is_int($metadataSize), 422, 'Metadados indisponíveis durante a aplicação.');
+ $metadataScan = app(MalwareScanner::class)->scan($metadata, $metadataSize, storage_path('app/private'));
+ abort_unless($metadataScan['result'] === 'clean', 423, 'Scan dos metadados do exemplar pendente ou inconclusivo.');
abort_unless(hash_file('sha256', $metadata) === $plan['metadata_sha256'], 409, 'Metadados alterados durante o scan.');
$metadataScan['signatures_at'] = $metadataScan['signatures_at']?->format(DATE_ATOM);
$batch = (string) Str::uuid();
@@ -138,17 +158,20 @@ class TerritoryGeometryImport
}
$feature = $source['features'][$i];
$id = (string) Str::uuid();
- $trace = ['authority' => 'Mozambique INE - Instituto Nacional de Estatistica', 'provider' => 'UNOCHA; exemplar hosted by World Bank', 'source_version' => $plan['edition'], 'source_sha256' => $plan['source_sha256'], 'metadata_sha256' => $plan['metadata_sha256'], 'source_url' => 'https://services.arcgis.com/iQ1dY19aHwbSDYIF/arcgis/rest/services/Mozambique/FeatureServer/'.($data['level'] + 2), 'source_properties' => $feature['properties'], 'source_scan' => $plan['scan'], 'batch_id' => $batch, 'purpose' => 'administrative_boundary', 'investment_site' => false, 'legal_currentness' => 'not_determined', 'match_basis' => 'unique_exact_name_and_matched_parent_after_case_and_diacritics'];
+ $trace = ['authority' => 'Mozambique INE - Instituto Nacional de Estatistica', 'provider' => 'UNOCHA; exemplar hosted by World Bank', 'source_version' => $plan['edition'], 'source_sha256' => $plan['source_sha256'], 'metadata_sha256' => $plan['metadata_sha256'], 'source_url' => 'https://services.arcgis.com/iQ1dY19aHwbSDYIF/arcgis/rest/services/Mozambique/FeatureServer/'.($data['level'] + 2), 'source_properties' => $feature['properties'], 'source_scan' => $plan['scan'], 'batch_id' => $batch, 'purpose' => 'administrative_boundary', 'investment_site' => false, 'legal_currentness' => 'not_determined', 'match_basis' => $row['match_basis'], 'correspondence' => $row['correspondence'], 'correspondence_version' => $row['correspondence_version'], 'correspondence_sha256' => $plan['correspondence_sha256']];
DB::insert('INSERT INTO geo_geometries(id,source_system,external_id,geo_location_id,geometry_type,geom,properties,data_classification) VALUES (?,?,?,?,?,ST_SetSRID(ST_GeomFromGeoJSON(?),4326),?::jsonb,?)', [$id, 'ine-cod-ab', $row['external_id'], $row['location_id'], strtolower($feature['geometry']['type']), json_encode($feature['geometry'], JSON_THROW_ON_ERROR), json_encode($trace, JSON_THROW_ON_ERROR), 'internal']);
$created[] = ['id' => $id, 'checksum' => $this->snapshotHash($id)];
}
- $result = ['batch_id' => $batch, 'level' => $data['level'], 'preview_hash' => $plan['hash'], 'expected' => $plan['expected'], 'resolved' => $plan['resolved'], 'created' => $created, 'inserted' => count($created), 'reused' => count($reused), 'reused_ids' => $reused, 'pending' => $plan['pending'], 'source_sha256' => $plan['source_sha256'], 'metadata_sha256' => $plan['metadata_sha256'], 'metadata_scan' => $metadataScan, 'published' => false, 'reason' => $data['reason']];
+ $result = ['batch_id' => $batch, 'level' => $data['level'], 'preview_hash' => $plan['hash'], 'expected' => $plan['expected'], 'resolved' => $plan['resolved'], 'created' => $created, 'inserted' => count($created), 'reused' => count($reused), 'reused_ids' => $reused, 'pending' => $plan['pending'], 'source_sha256' => $plan['source_sha256'], 'metadata_sha256' => $plan['metadata_sha256'], 'correspondence_version' => $plan['correspondence_version'], 'correspondence_sha256' => $plan['correspondence_sha256'], 'metadata_scan' => $metadataScan, 'published' => false, 'reason' => $data['reason']];
$this->audit($actor, $batch, 'geometry_import_applied', $result);
return $result;
});
}
+ /** @param array $input
+ * @return array
+ */
public function reverse(User $actor, string $batch, array $input): array
{
$this->guard($actor, true);
@@ -156,15 +179,31 @@ class TerritoryGeometryImport
return $this->receipt($actor, 'geometry-import-reverse', $data, function () use ($actor, $data, $batch) {
$event = DB::table('audit_events')->where('source_system', 'geometry-import')->where('entity_id', $batch)->where('action', 'geometry_import_applied')->first();
- abort_unless($event, 404);
+ abort_unless($event !== null, 404);
$old = DB::table('audit_events')->where('source_system', 'geometry-import')->where('entity_id', $batch)->where('action', 'geometry_import_reversed')->first();
if ($old) {
return json_decode($old->after_data, true);
}
$manifest = json_decode($event->after_data, true);
foreach ($manifest['created'] as $row) {
- DB::table('geo_geometries')->where('id', $row['id'])->lockForUpdate()->first();
+ $geometry = DB::table('geo_geometries')->where('id', $row['id'])->lockForUpdate()->first();
abort_unless($this->snapshotHash($row['id']) === $row['checksum'], 409, 'Geometria alterada ou publicada; reversão recusada.');
+ // Source hierarchy is a real import dependency even though it is not a geometry FK.
+ if (in_array((int) $manifest['level'], [1, 2], true)) {
+ $properties = json_decode($geometry->properties, true, 512, JSON_THROW_ON_ERROR);
+ $parentField = 'ADM'.$manifest['level'].'_PCODE';
+ $code = $properties['source_properties'][$parentField] ?? null;
+ abort_unless($code, 409, 'Correspondência original sem código territorial; reversão exige reconciliação.');
+ $descendants = DB::table('geo_geometries')->where('source_system', 'ine-cod-ab')->whereNull('deleted_at')
+ ->where('properties->source_version', $properties['source_version'])
+ ->where('properties->source_properties->'.$parentField, $code)
+ ->where(function ($query) use ($manifest) {
+ foreach (range((int) $manifest['level'] + 1, 3) as $level) {
+ $query->orWhere('external_id', 'like', '2019-06-07:adm'.$level.':%');
+ }
+ });
+ abort_if($descendants->exists(), 409, 'Limites descendentes dependem desta correspondência. Reverta primeiro postos, depois distritos e províncias; preserve os lotes anteriores.');
+ }
// Enumerate all real FKs, rather than assuming one consumer table.
$references = DB::select("SELECT n.nspname AS schema,t.relname AS table_name,a.attname AS column_name FROM pg_constraint c JOIN pg_class t ON t.oid=c.conrelid JOIN pg_namespace n ON n.oid=t.relnamespace JOIN pg_attribute a ON a.attrelid=c.conrelid AND a.attnum=c.conkey[1] WHERE c.contype='f' AND c.confrelid='geo_geometries'::regclass");
foreach ($references as $ref) {
@@ -188,6 +227,10 @@ class TerritoryGeometryImport
return hash('sha256', $r->value ?? 'missing');
}
+ /** @param array $data
+ * @param callable():array $operation
+ * @return array
+ */
private function receipt(User $actor, string $scope, array $data, callable $operation): array
{
return DB::transaction(function () use ($actor, $scope, $data, $operation) {
@@ -207,8 +250,17 @@ class TerritoryGeometryImport
});
}
+ /** @param array $data */
private function audit(User $actor, string $batch, string $action, array $data): void
{
DB::table('audit_events')->insert(['source_system' => 'geometry-import', 'entity_type' => 'geo_geometries', 'entity_id' => $batch, 'correlation_id' => $batch, 'actor_user_id' => $actor->id, 'action' => $action, 'after_data' => json_encode($data, JSON_THROW_ON_ERROR), 'data_classification' => 'internal']);
}
+
+ private function readFile(string $path): string
+ {
+ $contents = file_get_contents($path);
+ abort_unless(is_string($contents), 422, 'Exemplar/prova indisponível durante a leitura; operação recusada.');
+
+ return $contents;
+ }
}
diff --git a/app/Services/VirtualDeskInstallation.php b/app/Services/VirtualDeskInstallation.php
index dfd62956..745fd3eb 100644
--- a/app/Services/VirtualDeskInstallation.php
+++ b/app/Services/VirtualDeskInstallation.php
@@ -28,11 +28,15 @@ class VirtualDeskInstallation
database_path('migrations/2026_10_01_000200_create_simulation_execution_core.php'),
resource_path('js/components/investment-map-panel.tsx'), resource_path('js/pages/investment/detail.tsx'), resource_path('js/pages/partnerships/catalogue.tsx'),
...(glob(resource_path('js/pages/investor-path/*.tsx')) ?: [])];
- $files = [...$files, app_path('Services/VerifiedDocumentBinary.php'), app_path('Services/TerritoryGeometryImport.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), config_path('geometry-import.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
+ $files = [...$files, app_path('Services/VerifiedDocumentBinary.php'), app_path('Services/TerritoryGeometryImport.php'), app_path('Http/Controllers/TerritoryGeometryImportController.php'), config_path('geometry-import.php'), config_path('geometry-correspondences.php'), app_path('Http/Controllers/LandAssistanceController.php'), app_path('Http/Controllers/PartnershipExchangeController.php'), resource_path('js/pages/management/territory-geometry-import.tsx'),
base_path('bootstrap/app.php'), app_path('Providers/FortifyServiceProvider.php'), config_path('fortify.php'),
resource_path('js/pages/auth/login.tsx'), resource_path('js/pages/auth/two-factor-challenge.tsx')];
+ $files = [...$files, app_path('Services/OpportunityManagement.php'), app_path('Services/OpportunityRealEstateDraft.php'), config_path('portal.php'),
+ resource_path('data/investmoz-opportunity-modular.schema.json'), resource_path('js/components/app-sidebar.tsx'), resource_path('js/types/opportunity-management.ts'), base_path('vite.config.ts')];
+ $files = [...$files, resource_path('js/lib/portal-navigation.ts'), resource_path('js/components/portal-grouped-menu.tsx')];
sort($files);
+ $files = [...$files, ...PortalProfileAccess::fingerprintFiles()];
return hash('sha256', json_encode(array_map(fn ($file) => hash_file('sha256', $file), $files), JSON_THROW_ON_ERROR));
}
diff --git a/bootstrap/app.php b/bootstrap/app.php
index e478d9a6..5039960e 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -3,7 +3,9 @@
use App\Http\Middleware\EnsureSimulationRecoveryCookie;
use App\Http\Middleware\HandleAppearance;
use App\Http\Middleware\HandleInertiaRequests;
+use App\Http\Middleware\PortalProfileSession;
use App\Http\Middleware\PreserveFormFeedback;
+use App\Http\Middleware\ProtectProfileOpportunity;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Application;
@@ -26,6 +28,10 @@ return Application::configure(basePath: dirname(__DIR__))
$middleware->encryptCookies(except: ['appearance', 'sidebar_state', EnsureSimulationRecoveryCookie::NAME]);
$middleware->web(append: [
+ PortalProfileSession::class,
+ \App\Http\Middleware\ProtectPrivilegedIdentity::class,
+ \App\Http\Middleware\AuditProfileDecision::class,
+ ProtectProfileOpportunity::class,
HandleAppearance::class,
HandleInertiaRequests::class,
PreserveFormFeedback::class,
diff --git a/composer.json b/composer.json
index 5d86c12d..ff2b43c8 100644
--- a/composer.json
+++ b/composer.json
@@ -15,7 +15,8 @@
"laravel/fortify": "^1.37.2",
"laravel/framework": "^13.17",
"laravel/tinker": "^3.0",
- "laravel/wayfinder": "^0.1.14"
+ "laravel/wayfinder": "^0.1.14",
+ "opis/json-schema": "2.4.1"
},
"require-dev": {
"fakerphp/faker": "^1.24",
diff --git a/composer.lock b/composer.lock
index 3afec21d..fe08c43b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d0a5f283f588eb7a0f25e28797e62117",
+ "content-hash": "6a5afd60c9dc34bf3f21ae98a0b16c7b",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -3019,6 +3019,196 @@
],
"time": "2026-02-16T23:10:27+00:00"
},
+ {
+ "name": "opis/json-schema",
+ "version": "2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/json-schema.git",
+ "reference": "712827751c62b465daae6e725bf0cf5ffbf965e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/json-schema/zipball/712827751c62b465daae6e725bf0cf5ffbf965e1",
+ "reference": "712827751c62b465daae6e725bf0cf5ffbf965e1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "opis/string": "^2.0",
+ "opis/uri": "^1.0",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "ext-bcmath": "*",
+ "ext-intl": "*",
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\JsonSchema\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ },
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ }
+ ],
+ "description": "Json Schema Validator for PHP",
+ "homepage": "https://opis.io/json-schema",
+ "keywords": [
+ "json",
+ "json-schema",
+ "schema",
+ "validation",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/json-schema/issues",
+ "source": "https://github.com/opis/json-schema/tree/2.4.1"
+ },
+ "time": "2024-12-30T20:20:21+00:00"
+ },
+ {
+ "name": "opis/string",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/string.git",
+ "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/string/zipball/3e4d2aaff518ac518530b89bb26ed40f4503635e",
+ "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "ext-json": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\String\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ },
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ }
+ ],
+ "description": "Multibyte strings as objects",
+ "homepage": "https://opis.io/string",
+ "keywords": [
+ "multi-byte",
+ "opis",
+ "string",
+ "string manipulation",
+ "utf-8"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/string/issues",
+ "source": "https://github.com/opis/string/tree/2.1.0"
+ },
+ "time": "2025-10-17T12:38:41+00:00"
+ },
+ {
+ "name": "opis/uri",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/opis/uri.git",
+ "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/opis/uri/zipball/0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a",
+ "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a",
+ "shasum": ""
+ },
+ "require": {
+ "opis/string": "^2.0",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Opis\\Uri\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Marius Sarca",
+ "email": "marius.sarca@gmail.com"
+ },
+ {
+ "name": "Sorin Sarca",
+ "email": "sarca_sorin@hotmail.com"
+ }
+ ],
+ "description": "Build, parse and validate URIs and URI-templates",
+ "homepage": "https://opis.io",
+ "keywords": [
+ "URI Template",
+ "parse url",
+ "punycode",
+ "uri",
+ "uri components",
+ "url",
+ "validate uri"
+ ],
+ "support": {
+ "issues": "https://github.com/opis/uri/issues",
+ "source": "https://github.com/opis/uri/tree/1.1.0"
+ },
+ "time": "2021-05-22T15:57:08+00:00"
+ },
{
"name": "paragonie/constant_time_encoding",
"version": "v3.1.3",
diff --git a/config/geometry-correspondences.php b/config/geometry-correspondences.php
new file mode 100644
index 00000000..d58ae8db
--- /dev/null
+++ b/config/geometry-correspondences.php
@@ -0,0 +1,45 @@
+ 'ine-20190607-workbook-20261010-v2',
+ 'edition' => '2019-06-07',
+ 'catalogue_source_system' => 'cartografia-workbook',
+ 'catalogue_sha256' => '964a187ad32ea553b9e112cd159caa90b900050c42b7329594a75bcd798a96ff',
+ 'source_sha256' => [
+ 1 => 'ce5cd5f6090b7ba9ac78f919c9dd149f6c7880ab8275051a3398b1c6593fa989',
+ 2 => '16781986ac938bc8e81c9ca01a076b4bd46e333e8877645844d0cc7cd2919707',
+ 3 => 'ef11737c1ef68870bfcee67903352b7e554cb40ca39dd85f020c2a13631e1635',
+ ],
+ 'rows' => [
+ 1 => [
+ 'MZ05' => ['source_name' => 'Maputo', 'target_name' => 'Maputo Província', 'target_source_code' => '10', 'parent_source_code' => 'MZ',
+ 'basis' => 'INE ADM1 MZ05 designa a província Maputo; o exemplar separa Maputo City MZ06. Cadastro cartografia_moz.xlsx: Provincia Maputo Província, código10, sob Moçambique. Códigos10 e MZ05 pertencem a sistemas distintos.'],
+ 'MZ06' => ['source_name' => 'Maputo City', 'target_name' => 'Maputo Cidade', 'target_source_code' => '11', 'parent_source_code' => 'MZ',
+ 'basis' => 'INE ADM1 MZ06 designa Maputo City, distinta da província MZ05; tradução explícita City/Cidade. Cadastro cartografia_moz.xlsx: Provincia Maputo Cidade, código11, sob Moçambique. Não associa distritos urbanos ao distrito agregado da ediçãoINE.'],
+ ],
+ 2 => [
+ 'MZ1002' => ['source_name' => 'Cahora Bassa', 'target_name' => 'CAHORA-BASSA', 'target_source_code' => '03', 'parent_source_code' => 'MZ10',
+ 'basis' => 'Único distrito sob Tete nos dois exemplares; variante espaço/hífen. Mantém códigos próprios de cada fonte, edição INE 2019 e limites do exemplar, sem renomear o cadastro.'],
+ 'MZ0817' => ['source_name' => 'Ngauma', 'target_name' => 'N`GAUMA', 'target_source_code' => '14', 'parent_source_code' => 'MZ08',
+ 'basis' => 'Único distrito sob Niassa nos dois exemplares; variante de apóstrofo. Exige pai correspondido e código 14 no cadastro; não altera hierarquia.'],
+ 'MZ0704' => ['source_name' => 'Ilha De Moçambique', 'target_name' => 'CIDADE ILHA DE MOCAMBIQUE', 'target_source_code' => '04', 'parent_source_code' => 'MZ07',
+ 'basis' => 'Único ADM2 Ilha de Moçambique sob Nampula; cadastro qualifica explicitamente a cidade no mesmo nível Distrito, código04. Correspondência da edição INE 2019, não afirma limites atuais.'],
+ 'MZ0310' => ['source_name' => 'Maxixe', 'target_name' => 'CIDADE DE MAXIXE', 'target_source_code' => '10', 'parent_source_code' => 'MZ03',
+ 'basis' => 'Único ADM2 Maxixe sob Inhambane; cadastro Distrito CIDADE DE MAXIXE código10. Qualificação explícita Cidade, sem unir à área do distrito Inhambane.'],
+ 'MZ0720' => ['source_name' => 'Nacala-A-Velha', 'target_name' => 'NACALA-VELHA', 'target_source_code' => '18', 'parent_source_code' => 'MZ07',
+ 'basis' => 'Único distrito Nacala Velha sob Nampula; variante preposicional A. Preserva distinção de Nacala-Porto e Nacarôa; código18 apenas do cadastro.'],
+ 'MZ0502' => ['source_name' => 'Cidade Da Matola', 'target_name' => 'CIDADE DE MATOLA', 'target_source_code' => '01', 'parent_source_code' => 'MZ05',
+ 'basis' => 'Variação explícita da preposição Da/DE em Cidade de Matola. INE ADM2 MZ0502 sob Maputo MZ05; cadastro cartografia_moz.xlsx Distrito CIDADE DE MATOLA, código01 sob Maputo Província. Exige pai previamente correspondido; não altera limites ou hierarquia.'],
+ ],
+ 3 => [
+ 'MZ081201' => ['source_name' => "M'Sawize", 'target_name' => 'M`SAWIZE', 'target_source_code' => '02', 'parent_source_code' => 'MZ0812',
+ 'basis' => 'Variante exclusivamente de apóstrofo no mesmo pai ADM2 MZ0812 previamente correspondido; único posto código02. Nenhuma alteração do cadastro.'],
+ 'MZ011404' => ['source_name' => "N'Cumpe", 'target_name' => 'NCUMPE', 'target_source_code' => '05', 'parent_source_code' => 'MZ0114',
+ 'basis' => 'Variante exclusivamente de apóstrofo no mesmo pai ADM2 MZ0114 previamente correspondido; único posto código05. Nenhuma alteração do cadastro.'],
+ 'MZ011204' => ['source_name' => "N'Gapa", 'target_name' => 'N`GAPA', 'target_source_code' => '05', 'parent_source_code' => 'MZ0112',
+ 'basis' => 'Variante exclusivamente de apóstrofo no mesmo pai ADM2 MZ0112 previamente correspondido; único posto código05. Nenhuma alteração do cadastro.'],
+ ],
+ ],
+];
diff --git a/config/portal.php b/config/portal.php
index 128746b2..0a17eb40 100644
--- a/config/portal.php
+++ b/config/portal.php
@@ -1,6 +1,10 @@
(bool) env('PORTAL_PROFILE_ACCESS_ENABLED', false),
+ // Prepared increment; enable only in QA until the authenticated rollout is approved.
+ 'opportunity_dashboard_access_enabled' => env('PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED', false),
+ 'opportunity_specialized_drafts_enabled' => env('PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED', false),
'operator_name' => env('PORTAL_OPERATOR_NAME'),
'support' => [
'email' => env('PORTAL_SUPPORT_EMAIL'),
diff --git a/config/portal_profiles.php b/config/portal_profiles.php
new file mode 100644
index 00000000..7d53481c
--- /dev/null
+++ b/config/portal_profiles.php
@@ -0,0 +1,8 @@
+ storage_path('app/private/investmoz-v2/portal-profile-installation'),
+ // Scoped execution flags are set and reset only by the authenticated services.
+ 'authenticated_installation' => false,
+ 'bootstrap_authorized' => false,
+];
diff --git a/database/migrations/2026_10_10_040000_create_portal_profile_authorization.php b/database/migrations/2026_10_10_040000_create_portal_profile_authorization.php
new file mode 100644
index 00000000..1c289e8d
--- /dev/null
+++ b/database/migrations/2026_10_10_040000_create_portal_profile_authorization.php
@@ -0,0 +1,103 @@
+environment('testing')) {
+ $target = DB::selectOne('SELECT current_database() AS database, inet_server_port() AS port');
+ throw_unless(str_ends_with($target->database, '_test') && (int) $target->port === 55441, RuntimeException::class, 'Isolated QA required');
+ } else {
+ throw_unless(config('portal_profiles.authenticated_installation') === true, RuntimeException::class, 'Authenticated profile installation required');
+ }
+ Schema::table('users', fn (Blueprint $t) => $t->unsignedBigInteger('portal_access_revision')->default(0));
+ Schema::table('opportunities', function (Blueprint $t) {
+ $t->foreignId('owner_user_id')->nullable()->constrained('users')->restrictOnDelete();
+ $t->foreignUuid('organization_id')->nullable()->constrained('organizations')->restrictOnDelete();
+ $t->jsonb('workflow_context')->nullable();
+ });
+ Schema::create('portal_profile_requests', function (Blueprint $t) {
+ $t->uuid('id')->primary();
+ $t->foreignId('user_id')->constrained('users')->restrictOnDelete();
+ $t->foreignUuid('organization_id')->nullable()->constrained('organizations')->restrictOnDelete();
+ $t->string('representation_type');
+ $t->jsonb('opportunity_types');
+ $t->jsonb('document_ids');
+ $t->text('reason');
+ $t->string('status')->default('pending');
+ $t->unsignedBigInteger('version')->default(1);
+ $t->uuid('creation_key')->unique();
+ $t->foreignId('decided_by')->nullable()->constrained('users')->restrictOnDelete();
+ $t->text('decision_reason')->nullable();
+ $t->timestampTz('decided_at')->nullable();
+ $t->timestampsTz();
+ });
+ Schema::create('portal_role_assignments', function (Blueprint $t) {
+ $t->uuid('id')->primary();
+ $t->foreignId('user_id')->constrained('users')->restrictOnDelete();
+ $t->string('role');
+ $t->foreignUuid('organization_id')->nullable()->constrained('organizations')->restrictOnDelete();
+ $t->jsonb('opportunity_types');
+ $t->jsonb('responsibilities');
+ $t->string('policy_version')->default('profiles-v1-20261010');
+ $t->string('source');
+ $t->foreignUuid('request_id')->nullable()->constrained('portal_profile_requests')->restrictOnDelete();
+ $t->foreignId('approved_by')->constrained('users')->restrictOnDelete();
+ $t->timestampTz('starts_at');
+ $t->timestampTz('expires_at')->nullable();
+ $t->timestampTz('revoked_at')->nullable();
+ $t->timestampsTz();
+ $t->index(['user_id', 'role']);
+ });
+ Schema::create('portal_superuser_pair', function (Blueprint $t) {
+ $t->unsignedSmallInteger('id')->primary();
+ $t->foreignId('first_user_id')->constrained('users')->restrictOnDelete();
+ $t->foreignId('second_user_id')->constrained('users')->restrictOnDelete();
+ $t->unsignedBigInteger('version')->default(1);
+ $t->foreignId('approved_by')->constrained('users')->restrictOnDelete();
+ $t->timestampsTz();
+ });
+ Schema::create('portal_security_approvals', function (Blueprint $t) {
+ $t->uuid('id')->primary();
+ $t->string('kind');
+ $t->foreignId('requested_by')->constrained('users')->restrictOnDelete();
+ $t->foreignId('subject_user_id')->constrained('users')->restrictOnDelete();
+ $t->jsonb('scope');
+ $t->text('reason');
+ $t->foreignId('approved_by')->nullable()->constrained('users')->restrictOnDelete();
+ $t->timestampTz('expires_at');
+ $t->timestampTz('consumed_at')->nullable();
+ $t->timestampsTz();
+ });
+ DB::statement("ALTER TABLE portal_role_assignments ADD CONSTRAINT portal_role_name CHECK (role IN ('promoter','validator','publisher','auditor')), ADD CONSTRAINT portal_role_independent CHECK (approved_by <> user_id), ADD CONSTRAINT portal_role_period CHECK (expires_at IS NULL OR expires_at > starts_at)");
+ DB::statement('ALTER TABLE portal_superuser_pair ADD CONSTRAINT portal_pair_exact CHECK (id=1 AND first_user_id <> second_user_id AND version>0)');
+ DB::statement("ALTER TABLE portal_profile_requests ADD CONSTRAINT portal_request_status CHECK (status IN ('pending','approved','rejected','withdrawn')), ADD CONSTRAINT portal_request_independent CHECK (decided_by IS NULL OR decided_by <> user_id)");
+ DB::statement('ALTER TABLE portal_security_approvals ADD CONSTRAINT portal_security_independent CHECK (approved_by IS NULL OR approved_by <> requested_by)');
+ DB::unprepared('CREATE OR REPLACE FUNCTION guard_portal_superuser_pair() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION \'Superuser pair cannot be removed; use atomic replacement\'; END; $$; CREATE TRIGGER portal_pair_no_delete BEFORE DELETE ON portal_superuser_pair FOR EACH ROW EXECUTE FUNCTION guard_portal_superuser_pair(); CREATE TRIGGER portal_pair_no_truncate BEFORE TRUNCATE ON portal_superuser_pair FOR EACH STATEMENT EXECUTE FUNCTION guard_portal_superuser_pair()');
+ }
+
+ public function down(): void
+ {
+ foreach (['portal_role_assignments', 'portal_profile_requests', 'portal_superuser_pair', 'portal_security_approvals'] as $table) {
+ throw_if(DB::table($table)->exists(), RuntimeException::class, 'Preserve authorization history; disable access and reconcile restore');
+ }
+ throw_if(DB::table('opportunities')->whereNotNull('owner_user_id')->orWhereNotNull('organization_id')->orWhereNotNull('workflow_context')->exists(), RuntimeException::class, 'Preserve scoped opportunities');
+ throw_if(DB::table('users')->where('portal_access_revision', '<>', 0)->exists(), RuntimeException::class, 'Preserve session authorization history');
+ DB::unprepared('DROP TRIGGER portal_pair_no_delete ON portal_superuser_pair; DROP TRIGGER portal_pair_no_truncate ON portal_superuser_pair; DROP FUNCTION guard_portal_superuser_pair()');
+ Schema::dropIfExists('portal_security_approvals');
+ Schema::dropIfExists('portal_superuser_pair');
+ Schema::dropIfExists('portal_role_assignments');
+ Schema::dropIfExists('portal_profile_requests');
+ Schema::table('opportunities', function (Blueprint $t) {
+ $t->dropConstrainedForeignId('owner_user_id');
+ $t->dropConstrainedForeignId('organization_id');
+ $t->dropColumn('workflow_context');
+ });
+ Schema::table('users', fn (Blueprint $t) => $t->dropColumn('portal_access_revision'));
+ }
+};
diff --git a/docs/investmoz/v2/auditoria-portal/backlog.md b/docs/investmoz/v2/auditoria-portal/backlog.md
index fb634d73..274846b3 100644
--- a/docs/investmoz/v2/auditoria-portal/backlog.md
+++ b/docs/investmoz/v2/auditoria-portal/backlog.md
@@ -1,5 +1,163 @@
# InvesteMoz — backlog do lote 3
+
+## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em 2026-10-10T10:32:41+00:00: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **91 pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `profile_restore_20261010_104956_test:55441` → **295 tabelas com linhas/hashes iguais e 69 ficheiros fisicamente recuperados por hash**; todos os ficheiros referenciados recuperados por hash. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+## Contagens atuais por requisito
+
+| Estado | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+|parcial|3229|6379|
+|não implementado|145|446|
+|dependente de decisão concreta|5|5|
+|implementado mas não ativado|1|1|
+|concluído e demonstrado|6|7|
+
+3.386 requisitos verificáveis e 3.386 linhas consolidadas; 6.838 ocorrências de origem. Sem novo fecho integral; provas QA descritas por critério.
+
+
+
+## Próximo trabalho executável e decisões separadas — lote semântico atual
+
+| Prioridade / requisito | O que já tem prova QA | Falta / próxima ação e critério concreto |
+| --- | --- | --- |
+| P0 — UI-01/C37 | Diagnóstico/MFA preservados; ensaios HTTP21 não fecham18. | C37 e confirmação visual continuam pendentes conforme pedido. Quando retomados, dashboard→MFA→sessão→refresh→logout→novo login; rastreio sanitizado e primeiro ponto de perda. Nenhum novo teste visual solicitado agora. |
+| P1 — OP-04 / PROFILE-28/25 | Seis editores/regras no contrato do servidor; dez drafts e doze rejeições por campo recuperadas. | Observar cada categoria na UI21, erro junto ao controlo e nova sessão; reconciliar unidades aplicáveis, entidade/título/cadastro e limites urbanísticos com gates; completar Response/§27 apenas reutilizando entidades. Não regredir source/enums/IDs ou tornar campos incompletos obrigatórios para guardar. |
+| P1 — OP-03 / PROFILE-11/12/19 | Filas, parecer atribuído, resposta, revisão e coordenação editorial com task/hash/papéis; negações específicas. | Interface por24/25/29, reatribuição e revogação; incidentes, disponibilidade e revisão periódica. Parecer externo requer responsabilidade institucional concreta, não um ator fictício; aprovação interna não substitui decisão externa. |
+| P1 — GEO-03 / COUNTRY/STATS | Seis contratos ligam localização/documentos por IDs e país MZ; investimento recupera mercadoFR; editores consultam geometrias no nível selecionado. | Verificar visual de todos os consumidores afetados, país/origem→recuperação→filtro→estatística por formulário. Resolver nomes pendentes do pacote:31distritos+157postos; localidades/parcelas não inferidas de limites administrativos. Reutilizar importação autenticada/idempotente; publicação de camada é separada. |
+| P1 — OP-02 / LIB / PROFILE-23 | Originais por perfil, negação de organização23, cifragem/hash, PNG e duas derivadas ClamD; PDF do ensaio atual separado. | Continuar DOCX/XLSX, partilhas, PDFs/exportações/derivadas sem prova específica; preservar originals/versões. Consistência de erro404 recurso excluído versus423 scan pendente foi corrigida no consumidor de oportunidades. |
+| P1 — PROFILE-23 | Dois avisos preexistentes de league/commonmark identificados no lote anterior. | Avaliar consumidores e corrigir compatibilidade emQA; não apagar o achado nem atribuir a Opis. |
+| P2 — PROFILE-31 / OPS-01 | 190000confirmadaQA/ausenteativo;030/040QA;baseBalcãoativa instalada, hashes atualizados. | Construir instalação/bootstrap autenticados040 com duasidentidades reais explicitamente designadas; não mudar titulares nem retirar privilégio ativo automaticamente. Apósvisual, fixar candidata e renovarbackup/restauro dessa revisão; executar apenas migrações faltantes pelo mecanismo adequado. |
+
+Decisões independentes, sem bloquear este lote:
+
+1. **Concessão, financiamento, fornecimento e outros:** quais versões imutáveis de perfil modular, campos obrigatórios, documentos e gates são aprovadas para cada categoria? Sem esse contrato, guardar/editar funciona; submissão/revisão/publicação continuam bloqueadas.
+2. **SLA:** qual política versionada fixa prazo por tipo de tarefa, tolerância, número de ciclos e escalamento? Quem assume formalmente cada competência de coordenação, parecer técnico/jurídico, publicação e recurso? Manter prazo nulo e atribuição explícita até existir decisão; não usar nomes/prazos de QA como norma.
+3. **Condições sem regra inequívoca:** qual âmbito/citação estabelece a aplicabilidade de unidades/limites urbanísticos e materialidade? Como reconciliar o mínimo de um exercício do schema com entidades sem exercícios existentes? Não substituir valores ausentes por zero nem alterar silenciosamente a versão aceita.
+
+Não iniciar jornadas educativas novas. Mantêm-se cinco fases/19 etapas e URLs, dossier privado, oportunidade publicada, fontes oficiais aceites e histórico.
+
+
+
+## Próximo trabalho executável — incremento de 10/10/2026
+
+| Prioridade / requisito | Correção concreta seguinte | Critério de fecho e dependência |
+| --- | --- | --- |
+| P0 — UI-01/C37; DASH-01/C43 | Incorporar ensaio visual com Promotor 21 e, separadamente, investidor 18; registar falhas com URL, ação, estado e resposta sanitizada. | Login/MFA → dashboard → guardar → logout → nova sessão → recuperar, sem loop, perda ou acesso indevido; não substituível por HTTP. |
+| P1 — OP-04; PROFILE-28 | Completar editores e validações semânticas §25: grelhas de serviços/ónus, avaliação/documento, ocupação/título/cadastro, comunidades/consulta/benfeitorias, financeiros/beneficiário efetivo, NDA, governação e franquia; completar Response. Reutilizar contrato e entidades atuais. | Rascunho parcial recuperável; cada condição aplicável recusa dados inválidos e aceita dados/evidências completos; interface por categoria. Confirmar correspondências de objetos opacos do schema, sem alterar os significados legados silenciosamente. |
+| P1 — OP-03; PROFILE-11/12/19/21 | Completar filas/revisões e editoriais, reatribuição, pareceres, incidentes e recurso; manter hash da versão e independência. | Atores distintos e responsáveis explicitamente designados, motivos/evidência e histórico; revogação reavaliada. Ciclo principal já demonstrado por HTTP, não repetir o inventário. |
+| P1 — COUNTRY/STATS/GEO | Completar cobertura por formulário/consumidor, mapas e nomes cartográficos pendentes. | País/origem persistidos → recuperação → filtros/estatísticas; território cadastrado ≠ geometria ≠ mapa apresentado. 393 limites privados não encerram integração visual; faltam 31 distritos e 157 postos. |
+| P1 — OP-02/LIB/PROFILE-23 | Verificar tipos/partilhas/PDFs e derivadas ainda sem prova específica e autorizações do original. | ClamD real separado por operação; hashes/originais preservados; acesso permitido/negado e resultado visível. PNG/documentos do ciclo e duas derivadas já demonstrados. |
+| P1 — PROFILE-23 (achado adicional) | Composer audit apontou dois avisos preexistentes em `league/commonmark`: GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8. Identificar consumidores/configuração e preparar correção compatível em QA. | Prova local `workflow-composer-audit.json`; avaliar aplicação dos avisos e validar os consumidores afetados. Não atribuir aos três pacotes Opis nem declarar exploração demonstrada. |
+| P2 — PROFILE-22/31 | Configuração SLA versionada, instalaçao autenticada de perfis/dupla e preparação de ativação. | Decisões reais explícitas; ensaio backup/restauro da candidata posterior à visual; nenhum prazo ou titular real escolhido por QA. |
+
+**Decisões concretas:** (1) quais versões imutáveis de perfil, campos, documentos e gates são aprovadas para concessão, financiamento, fornecimento e outros? (2) qual política versionada fixa prazos, tolerância, ciclos e escalamento? (3) quem assume formalmente as responsabilidades institucionais e os exatamente dois superutilizadores ativos? Não bloqueiam as correções independentes, nem foram inferidas dos atores sintéticos.
+
+| Grupo dos pedidos abertos (projeção da mesma matriz) | Requisitos |
+| --- | ---: |
+| Parciais | 3187 |
+| Não implementados | 145 |
+| Preparados em QA | 46 |
+| Instalados com falha de acesso | 2 |
+
+Lista integral: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**, sob MFA de gestor/Auditor/Superutilizador QA. Cada cartão conserva o estado canónico, fontes, lacuna e próxima ação. “Preparado em QA” indica um escopo provado, não conclusão total.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Próximo lote: prioridade e critérios de fecho — 10/10/2026
+
+A matriz única tem 3.386 requisitos/linhas, 6.838 ocorrências e 3.380 requisitos abertos. As contagens abaixo agrupam o trabalho; mantêm o estado canónico de cada requisito. “Preparado em QA” identifica um escopo demonstrado, sem declarar todo o requisito concluído.
+
+| Grupo dos abertos | Requisitos |
+| --- | ---: |
+| Parciais | 3189 |
+| Não implementados | 146 |
+| Preparados em QA | 43 |
+| Instalados com falha de acesso | 2 |
+
+Lista integral pesquisável, derivada do mesmo CSV: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**. Acesso do gestor QA 17, Auditor 26 ou Superutilizador 27/30 com MFA. Não há permissões administrativas automáticas para o investidor.
+
+| Prioridade / requisitos | Próxima correção ou ensaio | Critério concreto |
+| --- | --- | --- |
+| P0 — AUD-UI-01; PROFILE-16/17/24 | Incorporar prova visual do login, atualização, logout, nova sessão e revogação; continuar diagnóstico sanitizado de C37. | Sessão recuperável e isolada; revogação efetiva; falha controlada sem autenticação indevida. |
+| P1 — PROFILE-05/06/07/25/30/32; AUD-DASH-01 | Executar o roteiro do dashboard, criação, recuperação, coedição, pedido/decisão e acessos negados; corrigir reproduções. | Resultado visível e persistente; mesmo ID/autor; autorização no servidor. |
+| P1 — AUD-OP-04; PROFILE-07/28 | Completar contratos Create/Patch/Response, formulário e adaptadores para entidades existentes. | Campos, regras, documentos e vínculos canónicos completos por categoria; o primeiro draft imobiliário de 24 campos não encerra o contrato. |
+| P1 — AUD-OP-03; PROFILE-08/09/11/12/19/20/21/22 | Submissão real, atribuição independente, pareceres/correções, aprovação/publicação, versão pública, incidentes e recurso. | Ciclo integral com atores distintos e contrato íntegro; nenhuma fixture de estado contada como submissão. |
+| P1 — AUD-GEO-02/03; AUD-FIELD-*; PROFILE-01/06 | Resolver os 31 distritos e 157 postos nomeados; verificar todos os seletores/mapas e âmbito provincial de autorização. | Cadastro, geometria e apresentação distinguidos por consumidor; selecionar → guardar → reabrir → mapa visível. |
+| P1 — AUD-COUNTRY-*; AUD-STATS-01 | Completar país/origem, recuperação, filtros e estatísticas por formulário. | Origem persistida e contabilizada; residência, país fiscal e origem dos fundos não substituem origem declarada. |
+| P1 — AUD-OP-02; AUD-LIB-01/02; AUD-SCAN-01 | Completar operações documentais, PDFs, partilhas e derivadas por tipo/perfil. | Scan próprio, permissões, revogação e recuperação por hash; original preservado. ClamD real já demonstrado não encerra operações restantes. |
+| P1 — PROFILE-13/14/15/18/23/26/31 | Completar operações críticas, concorrência da dupla, elevação, revalidação, privacidade, governança e instalação autenticada 040000. | Prévia, autorização, aplicação sem duplicação, recuperação e reversão verificadas; instalação separada da disponibilização. |
+
+**Decisões concretas para futura ativação:** PROFILE-29 — quais funções dos gestores ativos correspondem a Validador, Publicador, Auditor ou administração controlada; quem serão os dois titulares reais e o terceiro aprovador do bootstrap? PROFILE-22 — quais valores, versões e vigência dos SLA, tolerâncias e ciclos por tipo? PROFILE-16 — qual instância fará a recuperação de emergência se ambos perderem todos os meios? As cinco decisões canónicas incluem ainda as quatro pendências anteriores, preservadas por ID. Estas perguntas não impedem desenvolvimento QA independente.
+
+A edição por outros Promotores autorizados da mesma organização já foi decidida e aplicada em QA. Novas jornadas educativas não foram iniciadas. Workflow e contratos especializados continuam no backlog. [Correspondência e evidência](perfis-v1-reconciliacao.md), [roteiro](roteiro-manual-perfis-v1.md), [ativação](plano-ativacao.md).
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Prioridade corrente: Gestão de Oportunidades C43 —10/10/2026
+
+| Grupo de trabalho dos abertos | Requisitos | O que falta / próxima ação |
+| --- | ---: | --- |
+| Não implementados |145|Workflow integral segregado; rascunhos incompletos procura/capacidade e jornadas educativas ainda por fazer; demais critérios específicos não implementados no relatório por ID. Implementar workflow sobre draft/auditoria após contratos/gates; educação não começa enquanto prioridades abertas.|
+| Parciais |3183|Contrato imobiliário apenas API; DUAT/transações/campos/regras finais e vínculos; cartografia 31 distritos/157 postos/mapas por consumidor; relações/citações; acervo/PDFs/partilhas/derivadas; parâmetros fiscais; negócios/direitos/mandatos; reconciliação documental/UX e ativação. Inclui 4 decisões com estado original, sem bloquear tarefas QA independentes.|
+| Preparados emQA |19|Escopos concretos de rascunhos/recursos/maturidade, países/origem/estatísticas, seletor provincial, Balcão/percurso/CRM/orientação/simulador/parceria/fundiário/importação privada com provasQA. Completar critérios restantes na interface e operações/tipos ainda abertos; ativação permanece separada. Não são 19 requisitos globais concluídos.|
+| Instalados com falha de acesso |2|AUD-DASH-01(C43) e AUD-UI-01(C37/inspeção). Código/backendQA corrigidos nos escopos descritos; identificar sessão reportada e demonstrar dashboard/cliques e loginA/B completos. Confirmar visualmente sem conceder gestão ao investidor.|
+
+**Lista integral legível:**http://127.0.0.1:18097/qa-auditoria/pedidos-abertos, gestorQA 14/17.3349 cartões, um por ID, com pedido, lacuna, próxima ação, critério, fontes/versões/evidências e filtros de grupo/módulo. Vista derivada da [matriz única](matriz-requisitos.csv), sem edição nem estados paralelos; investidor 403. Os grupos são editoriais, distintos dos estados canónicos: 3199 parciais, 145 não implementados, 4 decisões, 1 implementado não ativado, 5 concluídos de âmbito restrito.
+
+Decisões humanas preservadas: pares exatos das 6 oportunidades com âncoras/clusters; identidade/termos/contactos do operador; URLs/serviços/responsáveis institucionais; modelo/indicadores/baseline de sucesso. Não reabrir aceitação das fontes oficiais; não inventar pares, parâmetros ou score.
+
+Ordem executável restante: 1)incorporar ensaio visual C43 e corrigir reprodução; 2)formulário/bindings/condições finais imobiliárias; 3)adaptadoresDUAT/transação; 4)gates e workflow segregado, sem autoaprovação; 5)continuar correspondências/cadastros/mapas, países/origem por formulário e operações documentais independentes. C37 continua pendente, sem repetir login do investidor neste lote; não iniciar jornadas educativas novas. Detalhes/ações por cadaID estão na vista integral.
+
+Aceitação C43: gestor 17/MFA parte de/dashboard→cliques→rascunho→guarda→outra sessão→recupera→edita→arquiva→restaura; feedback/ID/filtro/histórico visíveis; outra conta 403; dossier privado e público intactos. CritériosAPI satisfeitos não encerram o critério de interface.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Backlog corrente do lote independente — 10/10/2026
+
+Não aguardar C37 para executar os itens independentes. C37/P0 conserva a confirmação visual do login e cenáriosA/B; nenhuma nova tentativa solicitada neste lote.
+
+| Prioridade / requisito | Próxima correção executável e componentes | Dados/dependência concreta | Aceitação |
+| --- | --- | --- | --- |
+| P1 GEO-02/03; C38 |Resolver 31 distritos/157 postos com crosswalk versionado por fonte/edição/pai; reutilizar geo_locations/geo_geometries, TerritoryGeometryImport/Preview/Fields/ProvinceSelect. Conferir todos os consumidores na lista existente. |Exemplar/linha que distingue Cidade De Maputo agregado e Mandie 2 linhas; restantes 188 nomes no relatório. Sem polígonos de localidade disponíveis no exemplar retido. Fonte aceite não exige nova certificação. |Prévia mostra origem/pai/candidato único; aplicar/replay0duplicados/GETresultado; mapa e campo guardar/reabrir/limpar descendentes respeitam perfil; sem divulgar limites privados automaticamente. |
+| P1 COUNTRY01–04/06–07, STATS01 |Verificar os seletores/validações condicionais ainda não demonstrados na interface, por formulário da cobertura; corrigir qualquer lacuna executável API/persistência adicional. Reutilizar249ISO, DeclaredOriginStatistics e payloads existentes. |Backend específico renovado; não inferir origem da residência/fiscal/fundos. Valores antigos sem origem ficam desconhecidos. |POST/GET/nova sessão/filtro/tabela/estado vazio próprios; ZZ422sem escrita, revisão409, outra conta 403/404; conjuntos interests/desk/businesses separados. |
+| P0/P1 documental LAND01/PART01/LIB01–02/SCAN01; C39/C40 |Prosseguir restantes consumidores/tipos/perfis, renderização PDF/impressão e derivadas próprias; reutilizar VerifiedDocumentBinary, documents, scanner/jobs e auditoria. Implementar aplicação documental ativa autenticada antes de futura importação ativa; CLI permanece QA-only. |PDF/PNG/JPEG/fundiário/parceria e loteQA têm prova real; oportunidades PDF/PNG/3WebP e biblioteca/Balcão conservam provas anteriores. Arranque/reboot/assinaturas ClamD e GD PHPativo são pendências operacionais específicas. |Permissão antes dos bytes; scan do hash de cada original/derivada; original preservado; partilha/revogação recuperadas; incorreto/quarentena recusados; PDF efetivamente visível e impressão correta. Não generalizar prova de um consumidor. |
+| P1 OP03/04; C08 |Implementar adaptador do schema normativo110defs para OpportunityManagement/management_draft/version; validar Create/Patch por módulo antes de novas transições. Reutilizar OpportunityResources, serviços negócio/fundiário/documentos/territórios e audit_events. Em seguida revisão/devolução/aprovação/publicação com segregação autor/revisor/aprovador e versão aprovada. |Contratos9preparados; UUID de exemplo não renumera bigint. Estado fiscal/jurídico/decisão externa distintos de validação interna. Perfis adicionais exigem contrato aprovado da especificação, não campos inventados. |Rascunho incompleto permanece guardável; revisão precisa indica campo/regra/fonte; transição indevida403/422/409; alteração material invalida apenas aprovação da versão afetada; reviewer não se autoaprova; publicação separada; GET/auditoria/replay preservam IDs/história e permissões. |
+| P0 visual C37 + I1–I3 |Manter ensaio manualA/B existente em18097 com MFA sintético, sem credenciais na documentação. Incorporar cada resultado e corrigir falhas antes de fixar candidata. |Confirmar conta 18 no MFA e recuperar novo cookie/session sem alterar chave nem conta 13. Não bloqueia tarefas independentes acima. |A/B criação→gravação→nova sessão→aplicabilidade→ferramenta→resultado no dossier→Balcão→acompanhamento; tarefa paralela, ausência de mistura/acesso indevido;19 etapas/5fases mantidas. |
+| P1 OPS01 |Após critérios visuais e correções, fixar revisão e renovar backup/restauro/compatibilidade; gerar provas verdadeiras para a ordem consolidada. |Ativo fora da autorização; confirmar ledger/contagens atuais por leitura futura, não repetir instalações. |Recursos030000/percurso190000/flag/importação1→2→3/publicação separados; reversão GIS3→2→1 preserva catálogo/originais/receipts e recusa descendentes/uso/publicação. |
+
+Concluído neste lote apenas o âmbito específico demonstrado por prova:32correspondências, recuperação documental cifrada e controlos do loteQA; nenhum requisito transversal inteiro encerrado. Workflow/contratos preparados documentalmente continuam não implementados funcionalmente. Cinco fases/19 etapas e acesso direto a ferramentas preservados; nenhuma nova jornada educativa. [Matriz única](matriz-requisitos.csv), [evidências por consumidor](cobertura-percursos-i0-i3.md) e [plano](plano-ativacao.md).
+
+Complemento C41: novo PDF válido de 1página já gravado/escaneado/recuperado no servidor 18097, com5binários anteriores preservados. O placeholder antigo não é prova de renderização; no ensaio visual usar o novo recurso identificado em resources-real-http-qa.json, sem substituir/apagar o antigo. C42 retirou passwords fixas do script e rodou os dois atoresQA auxiliares; manter leitura das credenciais somente no ficheiro privado local, sem enviar na conversa. Não afeta conta 18/MFA/C37.
+
+**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores. 361 e2/39/179 são a baseline 09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.
+
+
## C37 — causa confirmada; seleção de conta QA corrigida — P0, visual pendente
O pedido de reabertura referia a conta esperada18. A captura manual21:22–21:24UTC demonstra que foi selecionada a conta13 restaurada. O MFA foi alcançado, mas a autenticação nunca se completou. Causa concreta: credenciais MFA da conta13 cifradas pela chave de origem, incompatíveis com a chave estávelQA; a conta18 sintética não foi desafiada nessa tentativa. Nenhuma chave, MFA ou conta13 foi alterada para contornar o problema.
diff --git a/docs/investmoz/v2/auditoria-portal/casos-reproducao.md b/docs/investmoz/v2/auditoria-portal/casos-reproducao.md
index 19554380..b83732f2 100644
--- a/docs/investmoz/v2/auditoria-portal/casos-reproducao.md
+++ b/docs/investmoz/v2/auditoria-portal/casos-reproducao.md
@@ -1,5 +1,127 @@
# Casos de reprodução e lacunas observáveis
+
+## Casos adicionais deste lote — sem reiniciar o inventário
+
+| Caso / requisito | Reprodução e resultado esperado | Observado, causa e correção | Prova / estado |
+| --- | --- | --- | --- |
+| C59 — PROFILE-31 / OPS-01 | Gestor confirmado com MFA consulta e aplica apenas 040000, após030000; repetir o mesmo pedido. Esperado:prévia, dependências e provas, uma instalação e um recibo, sem contas/grants automáticos. | A migração já tinha guarda, mas faltava rota/serviço/interface autenticados. Reutilizados Fortify, audit_events e cerimónia da dupla. Plano obsoleto/chave alterada409; falta de provas/dependência422; Auditor/Promotor403. | Testes de feature em schema vazio, repetição e bootstrap separados; servidor18097 já instalado:noop, replay idêntico, novaMFA e negações. Visual pendente. |
+| C60 — PROFILE-31 / recuperação | Em base isolada e schema vazio, down→instalar; depois impedir insert na auditoria e instalar. Esperado:reversão total deDDL/ledger se não houver recibo; retry possível; nenhum drop com uso/histórico. | No desenvolvimento do incremento foi introduzida remoção duplicada da colunausers; o ensaio encontrou Undefined column. Corrigida. Também reforçado down para contexto/organização sem autor e revisões de sessão; falha de auditoria devolve503 e não deixa schema/ledger parcial. | Testes específicos de reinstalação e falha de auditoria; históricos/contextos conservados. Não executado down no servidorQA utilizado, nem no ativo. |
+| C61 — OP-03 / publicação | Recuperar #30,#33,#32 e comparar estado da preparação, âmbito efetivo e catálogo. Esperado:restrito,público,aprovado sem disponibilização respetivamente. | Rótulo genérico “Publicado”/estado published não explicava o âmbito. Novo label/projeção consulta política efetiva do catálogo; botões distinguem disponibilização restrita de publicação pública. | JSON/Inertia e política pública verificados; nenhuma fuga pública observada. Perceção/ação visual pendente. |
+| C62 — PROFILE-31 / bootstrap | Propor duas contas distintas e terceiro gestor; candidato com MFA cifrado ilegível ou Auditor. Esperado:recusa controlada e nenhum titular criado. | A cerimónia conferia presença/confirmaçãoMFA, sem comprovar leitura do segredo no ambiente. Agora exige cifragem válida/estruturaMFA e recusa Auditor, mesmo com flags ainda desabilitadas. Sem key:generate/fallback ou remoção deMFA. | Teste422 e dupla permanece vazia; inicialização positiva com identidades sintéticas distintas. Não substitui C37/login visual. |
+| C63 — ambiente de testes / documental | Executar IndependentDocumentOperationsTest com o PHPCLI padrão. Esperado:GD disponível para gerar as imagens do ensaio. | Dois testes falharam por imagecreatetruecolor inexistente noCLI; o servidorQA já tinhaGD. Runner passa a carregar explicitamente a mesma extensãoGD para o processo de testes. | Regressão posterior27/600 semskips, scans reais e testes finais separados. Não atribuir esta falha ao servidorweb ou declarar GD ativo verificado. |
+| C64 — PROFILE-31 / recuperação e proteção | Em schema isolado com perfis habilitados, retirar a coluna de revisão e tentar desativar MFA/excluir conta. Esperado:sem alteração de identidade, recuperação e logout acessíveis. | Esquema parcial podia tornar o serviço de perfis indisponível e deixar middleware de proteção passar à frente. Agora recusa escritas com503, preserva MFA/conta e deixa o instalador apresentar a incoerência409; logout permanece permitido. | Teste específico, schema parcial não aplicado ao servidorQA nem ao ativo. Preserva leitura permitida e não cria bypass de recuperação. |
+
+C55 continua corrigida por operação:PDF eagoraDOCX/XLSX excluídos dão404, scanpendente continua423; restore preserva original. C37/C43/QA21/A-B permanecempendentes. Cada prova mantém API/persistência/interface separadas.
+
+
+
+## Reprodução e evidências adicionais — mesmo inventário
+
+| Caso / requisito | Passos e esperado | Observado / causa | Correção e estado |
+| --- | --- | --- | --- |
+| C55 — OP-02 | QA21→PDF limpo→exclusão lógica→GETdownload. Esperado: recurso indisponível, sem atribuir falha de scan. Restaurar e recuperar original. | HTTP423/quarentena porque download juntava row inexistente à condição de scan. | Separa ausência/exclusão404 de quarentena423; teste específico e ensaioPDFweb18097. Originais/hash preservados; visualpendente. Prova da falha `opportunity-semantic-documents-http-qa-attempt1.json`. |
+| C56 — OP-04/PROFILE-25 | Promotor21 abre editor de categoria; campos de núcleo devem ter um único valor/controlo e erros associados. | Revisão do código: formulário legado e contrato canónico duplicavam título/território/campos, com valores independentes. | Contrato canónico único no modo perfil; formulário legado continua na gestão própria. BuildQA/TS e payloadAPI; observação visualpendente. |
+| C57 — OP-04/PROFILE-28 | Guardar fim anterior ao início/ciclo/serviços incompletos/documento estrangeiro/comunidade sem consulta/financeiros incompletos; recuperar noutra sessão; submeter. | Regras anteriores aceitavam objetos opacos sem semântica suficiente. | 12negativas422 com caminho de campo; rascunhos recuperados; seis cenários completos submetidos/revistos. Não extrapolar a regras jurídicas ainda sem âmbito/gate. |
+| C58 — OP-03/PROFILE-19/12 | Parecer com destinatário técnico/jurídico; responder outro ator; aprovar pendente. Depois atribuir publicação e tentar outro Publicador. | Fluxo anterior não tinha destinatário/resposta/fila completa nem atribuição editorial. | #30destinatário29/resposta/tarefa;outro403/aprovação422; #33filaeditorial29/outro25publica403/designado29publica. Sem gateautoaprovado/prazofictício; visualpendente. |
+| 190000 — OPS-01/PROFILE-31 | Comparar ledger/duascolunas/definição QA eativo, distinguir migraçãoBalcão07 depercurso09. | Plano anterior omitia recurso ainda ausenteativo. | 09/190000confirmadaQA e ausenteativo, necessária/nãosubstituída; seqüência autenticada recolocada. Nenhuma execuçãoativa. |
+
+
+
+## Reproduções adicionais do incremento — 10/10/2026
+
+| Caso / requisito | Reprodução e esperado | Falha ou risco encontrado / causa | Correção e evidência separada |
+| --- | --- | --- | --- |
+| C44 (complemento) — OP-04/PROFILE-28 | Guardar rascunho especializado parcial → completar → submeter; condições da categoria devem ser verificadas. | Submit permanecia bloqueado pelo contrato não integrado; a extração dos Create não conservava as condições `allOf` do schema original. | Adapter recupera condições, usa validação Draft2020-12 e recursos existentes. Dez rascunhos recuperados; seis submissões aceites/ quatro recusadas por perfil. Semântica integral e visual pendentes. |
+| C50 — OP-04 | Imobiliário `sale`, `price:null`: guardar rascunho permitido, submeter recusado. | Campo nullable e `required` não garantiam preço positivo para venda. | Regra explícita positive; oportunidade19: draft aceite, submit422, preço corrigido e submit200. |
+| C51 — PROFILE-25 | Após submissão, continuar pela visualização; edição deve ficar fechada. | Código da ação recarregava `/edit`, que passa corretamente a403 após submissão; o primeiro acesso HTTP Validador a essa rota confirmou a restrição, não uma falha de autorização. | Ações navegam `/view`; edição privada tem link apenas autorizado. API/props/build verificados; transição visível ainda pendente. |
+| C52 — PROFILE-08/12/25 | Publicada → pedido de alteração → pesquisar título privado/estado → recuperar; ficha pública não pode mudar antes de aprovação. | Consulta/contagens usavam só título e estado públicos, ocultando a posição da proposta privada. | Consulta já autorizada usa estado/título de trabalho, preservando publicação. Teste específico do filtro/contagem e HTTP público19 original até suspensão. Visual pendente. |
+| C53 — GEO-03/PROFILE-12 | Duas localizações, principal em segundo lugar → aprovar/publicar; território apresentado deve ser o principal. | Revisão de código encontrou uso da primeira posição da lista, que não define a principal. | Filtra `is_primary`; HTTP oportunidade28 apresenta ID/distrito principal correto. Teste específico isolado; mapa visual pendente. |
+| C54 — PROFILE-19 | Revisão → correção → resubmeter; ou revisão → rejeitar. Esperado: tarefa anterior concluída, nova tarefa sem atribuição presumida. | Código mantinha revisão antiga aberta e podia herdar atribuição numa nova versão. | Conclui tarefas com motivo/histórico; limpa atribuição na submissão. HTTP28: correção/resubmissão/publicação/suspensão, nenhuma tarefa aberta ao final; HTTP29: rejeição fecha revisão. |
+| C37 / C43 | Login investidor18; dashboard Promotor21 e ciclo de ações. | Não houve demonstração visual atual no navegador. | Mantidos pendentes, roteiro e conta preparados; não fechar por HTTP, props ou total de testes. |
+
+Rejeições esperadas adicionais: motivo curto422, confirmação de publicação falsa422, hash de prévia errado409, self/multirole403, recurso pelo rejeitor/organização403, publicação fundiária com autorização externa pendente422. Provas privadas específicas preservam sequência/estado, sem segredos.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Reproduções adicionais de perfis — 10/10/2026
+
+C37 permanece pendente; não houve nova tentativa da conta 18 nem fecho visual. C43/C44 preservados.
+
+| Caso / requisito | Reprodução | Esperado | Observado e causa | Correção/prova | Pendente |
+| --- | --- | --- | --- | --- | --- |
+| C45 — PROFILE-05/06/25, AUD-GEO-03 | Promotor 21: dashboard → Nova → seletor/mapa; comparar chamadas territoriais. | Perfil autorizado consulta, grava e recupera território/geometria. | Consumidor chamava rotas management reservadas a manage-portal. Inspeção de código/rotas; nenhuma captura visual anterior. | Alias autorizados reutilizam serviços: 11 províncias, Cabo Delgado guardada/recuperada, uma área API. profiles-v1-current-version-qa.json. | Desenho/cliques por perfil e restantes consumidores. |
+| C46 — PROFILE-06/07/10/29 | Gestor sem perfil: API administrativa de contexto da oportunidade privada; território, prévia de origem e subjects. | Allowlist legada não revela/edita o privado v1. | Rotas auxiliares tinham apenas can:manage-portal, sem política do registo. Lacuna identificada em código, sem realizar escrita indevida. | Middleware cobre aliases/payload; subjects/dashboard/catalog usam âmbito. Testes 403/lista vazia. | Outras relações/filas e âmbito provincial. |
+| C47 — PROFILE-04 | Rejeitar pedido com approved_types=[] e conferências false. | Rejeição fundamentada sem inventar conferência. | Ensaio respondeu 422: approved_types required rejeitava array vazio. | present|array; não-vazio só na aprovação; accepted_if só approved. Teste rejeita sem conceder e preserva conferência false; decisão própria 403. | Decisão na interface. |
+| C48 — PROFILE-15/16/24/26 | Titular 30: DELETE MFA, DELETE conta, PATCH email. | Manter MFA obrigatório, dupla e histórico. | Regra específica da identidade privilegiada v1 não existia. Lacuna identificada em código; nunca se desativou MFA para ensaio. | ProtectPrivilegedIdentity, 403 e auditoria; recovery Fortify noutra sessão/reuse negado; trigger DELETE testado. | Visual e recuperação institucional de emergência. |
+| C49 — PROFILE-10/29 | Conta sintética com papéis v1 e allowlist legada: abrir Nova legada, POST draft legado; depois escrita administrativa com Auditor. | Não contornar organização/tipo nem a restrição do Auditor pela acumulação. | Exceção legada podia autorizar escrita mais ampla. Identificada em código, sem usar conta ativa ou criar dados fora do âmbito. | Decisão documentada antes da correção; legacyWriteAllowed usa histórico; 403 na criação e escrita, atalho legado ausente nas props. Gestor sem atribuição v1 preservado. | Interface, conciliação dos gestores reais e consumidores restantes. |
+
+Submissão real do rascunho 15 → 422 por contrato Create ausente é lacuna funcional mantida, não falha de MFA/autenticação. A fixture de revisão não demonstra submissão integral. Evidências por critério em profiles-v1-final-qa.xml, http-qa, recovery-audit, current-version e preservation; JSON/HTML não substitui interface.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Casos adicionais C43/C44 —10/10/2026
+
+**C43 — causas encontradas no código/compilação:**(1)AppSidebar mostrava só o primeiro filho de cada grupo, descartando oportunidades; (2)menu Painel apontava /investidor mesmo para gestor; (3)dashboard de gestão colocava criação no fim como Criar oportunidade, sem rótulo Nova oportunidade. A secção de gestão só é devolvida pelo backend a contas verificadas em portal.managers; o seu ocultamento para investidor é autorização esperada, não motivo para conceder perfil administrativo.
+
+Correção QA: atalhos Gestão de Oportunidades/Nova oportunidade no início do dashboard, sidebar/menu agrupado; Painel da gestão→/dashboard, dossiers→/investidor. Nova ação archive conserva o rascunho em status archived/deleted_at=null; delete/exclusão lógica mantém o contrato anterior. Restauro volta a draft, ID/histórico intactos, sem publicação. Código usa flags false por omissão; QA usa assets `public/build-qa-opportunities`, versão Inertia desse manifesto. **`public/build` ativo manteve SHA 75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94.** Recursos 030000 não são requisito para navegar/criar rascunho básico.
+
+**C44 — progresso específico:**primeiro adaptador imobiliário aceita campos fornecidos nas 24 propriedades realEstatePatch, validando tipos/enums/limites/UUID e recusando campos desconhecidos/de resposta. Guarda/merge privadamente no management_draft atual. Ainda faltam formulário especializado, vínculos canónicos, condições finais/Create/Response, DUAT/transação e workflow. Nenhuma coleção/tabela paralela, renumeração ou decisão externa criada. O.source.json conserva o retrato histórico da extração, não certifica o estado runtime atual.
+
+C43, reprodução de código/assets: seguirPainel do catálogo com gestor→/investidor; na sidebar, grupoGestão→primeiro filho/interests apenas; no /dashboard a criação está no fim e tem label Criar oportunidade. Esperado: gestor chega ao seu dashboard e encontra Gestão/Nova sem URL decorado; investidor conserva área privada. Observado: links omitidos/destino partilhado/nome diferente. Evidência do utilizador ainda sem URL/conta; não se afirma que o seu perfil é o motivo. Também havia somenteExcluir rascunho no rascunho inicial, com delete→deleted_at em vez dearchive→status archived; corrigido separadamente sem alterardelete.
+
+C44, reprodução anterior por inspeção: categoriareal_estate disponível, mas payloadreal_estate não fazia parte dos campos validados/persistidos. Esperado: guardar dados parciais e recuperar privadamente. Correção limitada: adaptador 24 propriedadesPatch; cinco negativos HTTP reais 422 sem mutação. Não se inventou ensaioHTTP pré-correção nem se declarou o contrato integral concluído.
+
+- `dashboard-active-readonly.json`: configuração/contas elegíveis/instalação/manifesto ativo, sem boot HTTP/escrita de sessão no ativo.
+- `dashboard-opportunities-http-qa.json`: links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtro archived→restore→GET. Oportunidade QA 13, ID estável/quatro eventos, 12 originais e relações/documentos/dossiers preservados; 6 publicadas mantidas; outra conta 403.
+- `dashboard-manager-mfa-http-qa.json`: gestor 17, MFA em duas sessões→dashboard→gestão→recuperação/reload→logout; 0 alterações de registos. `dashboard-navigation-catalogue-qa.json`: menu Painel da gestão→/dashboard, dossiers privados→/investidor, atalhos únicos e ausência de gestão para investidor.
+- `real-estate-draft-http-qa.json`: outra oportunidade QA 14, rascunho imobiliário parcial no draft existente→nova sessão→patch merge→cinco 422 sem mutação→outsider 403; schema normativo SHA 9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
+- `dashboard-real-estate-qa.xml`: casos nomeados Dashboard OpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest, 8 ensaios/201 asserções. Typecheck, build QA e PHPStan dirigidos passaram; contagem não substitui os critérios visuais.
+- `resource-originals-preservation-http-qa.json`: cinco binários anteriores preservados e novo PDF válido recuperado/parseado, 0 novos recursos. Prova ClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
+- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`: fontes/trechos/IDs/versões preservados, 3354 requisitos/linhas e 5830 ocorrências; 3349 abertos apresentados uma vez cada. Estado AUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Casos adicionais do lote independente — 10/10/2026
+
+### C38 — correspondências provinciais impediam descendentes; ambiguidade nominal bloqueava lote independente — P1
+
+Requisitos AUD-GEO-01/02/03. Reproduzir préviaQA com o exemplarINE2019 e cadastro aceites: Maputo/Maputo City não correspondem literalmente a Maputo Província/Maputo Cidade; Cidade Da Matola não corresponde a CIDADE DE MATOLA. Esperado: equivalência explicitamente versionada por exemplar/pai, sem alterar nomes/códigos/IDs/hierarquia. Observado baseline 9/120/232 e2/39/179 pendentes; descendentes sob os pais Maputo ficam não resolvidos. Causa: correspondência apenas nominal exata, sem crosswalk dessas variantes concretas.
+
+Correção: três entradas explícitas com códigos de ambos os sistemas preservados, hash do exemplar/workbook e pai obrigatórios. Descendentes exatos tornam-se elegíveis; via gestor/MFA/importação18097 foram inseridas 2 províncias+8 distritos; primeira execução ficou interrompida na prévia de postos por Mandie com 2 candidatos do cadastro. A classificação inicial correspondence_conflict bloqueava outros postos inequívocos. Corrigida para ambiguous_name pendente quando são nomes iguais sem crosswalk explícito; conflitos de uma correspondência explícita continuam impeditivos. Continuação reutiliza as 10anteriores e insere 22 postos, sem repetir originais. Mandie corresponde a duas linhas reais do workbook e não foi fundido/escolhido por código presumido.
+
+Evidência: preservationQA393/32 novas/361 originais/1990catalogueigual; HTTPconsumidores32gestor/0 públicos; sete casos QAincluem edição/pai/conflictos/replay/reversão3→2→1e recusa de pai com descendente ativo sem FK. Prévia e mapas na interface pendentes. Lacunas0/31/157,188 nomes listados; CidadeDeMaputo agregado não é um distrito urbano individual. Ativo não alterado.
+
+### C39 — fundiário e sala de parceria recusam404 um original cifrado íntegro — P0 de recuperação
+
+Requisitos AUD-LAND-01/PART-01/SCAN-01. QA de feature: criar caso fundiário/sala próprios; anexar PDF/PNG/JPEG, completar scan real/hash; reutilizar o mesmo documents canónico com storage_encryption Laravel e bytes cifrados privados; pedir GET /investidor/terra-duat/{id}/documentos/{attachment} ou /parcerias/salas/{id}/documentos/{attachment} pelo ator autorizado. Esperado200 com bytes originais, preservando autorização/scan/hash. Observado404 nos dois consumidores, reproduzido em document-independent-before-qa.xml. Causa: hash do ciphertext comparado diretamente ao SHA do original e binário devolvido sem VerifiedDocumentBinary.
+
+Correção: serviço comum de decifragem/integridade/quarentena; selecionar metadata cifragem sem expor chave; conservar autorização original. Novos uploads registam size_bytes/uploaded_by antes ausentes, leituras fundiárias em audit_events existente. Evidência pós-correção: document-independent-qa.xml, PDF/PNG/JPEG originais reais/ClamD/perfis/partilha/revogação/GET/tamper404. Impressão apenas props200; renderizaçãoPDF/browser pendentes. Nenhum ciphertext/segredo exportado, nenhum original substituído/publicado, nenhuma migration/dado ativo alterado.
+
+### C40 — --actor não comprova autorização nem autenticação de lote documental — P1
+
+Requisitos AUD-LIB-02/OPS-01. Identificado por revisão do comando documents:import-batch: --actor antes só exigia IDexistente, sem can:manage-portal nem guarda de alvoQA para --apply. Não houve execução ativa nem alegação de exploração ativa. Esperado: ensaio de escrita isoladoQA com ator autorizado; aplicação ativa somente autenticada pelo mecanismo previsto. Correção: environmenttesting+SQLreal*_test:55441+loopback+URLvazia e User::can('manage-portal') antes de escrita. Ambienteproduction recusado mesmo apontado a uma baseQA; nomear ator não autentica.
+
+document-batch-independent-qa.xml demonstra recusas sem DB/ficheiros novos, prévia privada/replay/dedup/hash/ClamDreal/perfis e conflito de identidade sem substituição. Aplicação documental ativa autenticada continua pendente; não adaptar CLIpara o ativo. Este limite não impede os ensaiosQA nem consulta/read-only. Nenhuma publicação automática.
+
+### C41 — PDF sintético com cabeçalho não comprova legibilidade — lacuna de QA
+
+Requisitos AUD-SCAN-01/OP-02. Revisão do fixture histórico de portal-resources-real-http-qa.py encontrou apenas cabeçalhoPDF e terminador; parser independente recusa-o sem startxref/estrutura. Esse ensaio demonstra upload/scan/hash/download dos bytes, não PDF legível ou renderizado. Não é diagnóstico de um documento oficial nem falha presumida do leitor do portal.
+
+CorreçãoQA: gerador sintético válido de 1página, árvore de objetos/xref/texto; parser independente confirma original e variante de lote. Novos testes fundiário/parceria/lote reexecutados com esses bytes/ClamDreal. Anexado um novo recurso válido à oportunidade sintéticaQA12 no servidor 18097; original placeholder e PNG/3WebP anteriores preservados por hash, sem repetir instalação nem criar oportunidade/cartografia/jornada duplicada. Novo PDF download/ClamD/403outra conta/logout/nova sessão/recuperação passaram. Evidências document-types-fixture-qa.json/resources-real-http-qa.json/resource-originals-preservation-http-qa.json. Renderização visual PDF/impressão continua pendente.
+
+### C42 — passwords fixas de atores sintéticos no scriptQA — corrigido, sem exposição ativa
+
+Durante a leitura de um script legado apareceram passwordsQA fixas. Correção imediata com portal-resource-http-actors-qa.php e guarda real do destino: dois atores sintéticos auxiliares, passwords aleatórias privadas e remember tokens rodados. Diretório de sessõesQA validado; nenhuma sessão desses atores restante para invalidar. MFA mantido byte a byte, conta 18 preservada por hash da linha; nenhuma chave/conta/dado ativo alterado. ScriptHTTP passa a ler credenciais do ficheiro privado local; suporte a MFA normal permanece. Não repetir valores, cookies ou OTP em prova/captura. Evidência sanitizada resource-http-actors-rotation-qa.json; login/logout/nova sessão dos perfis auxiliares demonstrados no servidor pelo lote documental, separados do C37 investidor.
+
+
## C37 — causa confirmada; seleção de conta QA corrigida — P0, visual pendente
O pedido de reabertura referia a conta esperada18. A captura manual21:22–21:24UTC demonstra que foi selecionada a conta13 restaurada. O MFA foi alcançado, mas a autenticação nunca se completou. Causa concreta: credenciais MFA da conta13 cifradas pela chave de origem, incompatíveis com a chave estávelQA; a conta18 sintética não foi desafiada nessa tentativa. Nenhuma chave, MFA ou conta13 foi alterada para contornar o problema.
diff --git a/docs/investmoz/v2/auditoria-portal/cobertura-percursos-i0-i3.md b/docs/investmoz/v2/auditoria-portal/cobertura-percursos-i0-i3.md
index 45df776a..5ae48a05 100644
--- a/docs/investmoz/v2/auditoria-portal/cobertura-percursos-i0-i3.md
+++ b/docs/investmoz/v2/auditoria-portal/cobertura-percursos-i0-i3.md
@@ -1,5 +1,147 @@
# Cobertura por percurso e consumidor — continuação QA
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco é a evidência mais recente desta matriz; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Cobertura após perfis v1 — 10/10/2026
+
+I0–I3 permanecem em QA. Cinco fases e 19 etapas preservadas, sem renumeração. C37, A/B e C43 visuais continuam pendentes. A autorização organizacional reutiliza OpportunityManagement, Resources, Fortify e entidades existentes; nenhuma jornada educativa nova foi iniciada.
+
+- Interface: preparada e compilada, sem observação no navegador. Roteiro manual de perfis inclui acessos permitidos/negados; A/B preservam o roteiro existente.
+- API: links descobertos no dashboard, rascunho 15 recuperado noutra sessão, coedição 22 e negações por tipo/organização/múltiplos papéis. Seletores autorizados e geometria do Promotor funcionam; submissão integral permanece bloqueada por contrato incompleto.
+- Persistência: autor, ID, versão e histórico preservados; Cabo Delgado recuperada com o mesmo ID/nome. Pedido de Promotor, comprovativos, auditoria, revogação e dupla demonstrados nos escopos descritos.
+- Documentos: quatro comprovativos sintéticos com ClamD real e hash recuperável; não generalizar às operações restantes. Originais anteriores preservados em 18 tabelas.
+- Ativo: exclusivamente READ ONLY, sem instalação/flag de perfis. 020000 instalada; recursos/percurso ainda ausentes. Mesma matriz: 3.386 requisitos, 6.838 ocorrências.
+
+Coordenadores, pareceristas, suporte e recurso estão explicitamente mapeados na reconciliação. Filas, decisões, SLA e incidentes funcionais continuam parciais ou não implementados no backlog. 393 geometrias privadas QA não encerram a integração visual; permanecem 31 distritos/157 postos nomeados.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Cobertura adicional: dashboard e draft imobiliário —10/10/2026
+
+- `dashboard-active-readonly.json`: configuração/contas elegíveis/instalação/manifesto ativo, sem boot HTTP/escrita de sessão no ativo.
+- `dashboard-opportunities-http-qa.json`: links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtro archived→restore→GET. Oportunidade QA 13, ID estável/quatro eventos, 12 originais e relações/documentos/dossiers preservados; 6 publicadas mantidas; outra conta 403.
+- `dashboard-manager-mfa-http-qa.json`: gestor 17, MFA em duas sessões→dashboard→gestão→recuperação/reload→logout; 0 alterações de registos. `dashboard-navigation-catalogue-qa.json`: menu Painel da gestão→/dashboard, dossiers privados→/investidor, atalhos únicos e ausência de gestão para investidor.
+- `real-estate-draft-http-qa.json`: outra oportunidade QA 14, rascunho imobiliário parcial no draft existente→nova sessão→patch merge→cinco 422 sem mutação→outsider 403; schema normativo SHA 9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
+- `dashboard-real-estate-qa.xml`: casos nomeados Dashboard OpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest, 8 ensaios/201 asserções. Typecheck, build QA e PHPStan dirigidos passaram; contagem não substitui os critérios visuais.
+- `resource-originals-preservation-http-qa.json`: cinco binários anteriores preservados e novo PDF válido recuperado/parseado, 0 novos recursos. Prova ClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
+- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`: fontes/trechos/IDs/versões preservados, 3354 requisitos/linhas e 5830 ocorrências; 3349 abertos apresentados uma vez cada. Estado AUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.
+
+Gestão desde/dashboard: API/destinos reais/gravação/novasessão/recuperação/arquivo/restauro demonstrados; interfacepending. Formulário especializado imobiliário ausente; 24 campos dePatch são adaptaçãoAPI parcial. Nenhuma cobertura cartográfica/países/origem/documental anterior promovida por esses ensaios. Gestor 17/MFA distinto do investidor 18; C37 eA/B visuais permanecem abertos.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Evidência independente por consumidor — 10/10/2026
+
+QA web desk_restore_20261009_174726_test:55441 e ensaios separados investmoz_test:55441. C37/login investidor e A/B visuais continuam pendentes. Nenhuma sessão de navegador foi certificada; a nova autenticação HTTP deste lote foi do gestor cartográficoQA, distinta do investidor18.
+
+**Países — provas renovadas por formulário na tabela existente abaixo:** countries-independent-qa.xml contém os métodos InvestmentWorkspaceTest (perfil/empresa/manifestação/CRM), PortalAuditContinuationTest (manifestação pública/quatro tipos de apoio/catálogo/Balcão territorial), PortalAuditNextLotTest (wizard negócios e fundiário), PortalOriginCompatibilityTest (origem legada) e InvestorGuidanceTest (Balcão). countries-forms-independent-qa.xml contém especificamente BusinessMarketplacePublicTest::test_interest_is_limited_to_published_business_and_deduplicated_idempotently, InvestmentPortfolioTest::test_personal_journey_is_isolated_and_retries_do_not_duplicate_interest_or_event, PortalAuditConsumerLotTest::test_all_three_desk_forms_save_recover_countries_and_support_authorized_corrections e PortalAuditContinuationTest::test_simulator_recovers_iso_countries_in_private_draft_without_reinterpreting_legacy_values. A contagem22inclui outros testes pela palavra original; não representa 22 formulários/requisitos de países. Cada linha abaixo mantém critérios visuais próprios abertos.
+
+**Cartografia — três estados:** cadastro 1920 referências/1990 geo_locations incluindo70países; geometria administrativa393/581da edição 2019; apresentação renderizada não verificada. geometry-crosswalk-consumers-http-qa.json recupera 32 novos limites por endpoint gestor e 0 públicos, nomes guardados de ambas as províncias Maputo correspondem a um IDúnico. geometry-consumers-path-qa.json recupera393por serviço. ProvinceSelect partilhado liga este IDao preview e conserva texto antigo desconhecido; isso prepara PortalInvestidor/portal-services/AI, sem alegar resultado visual individual. TerritoryFields/territory-preview/MapaBolsa/InvestmentMapPanel existentes reutilizados. Localidade pode ter contexto ancestral, nunca polígono próprio inferido. Correspondências0/31/157 pendentes; todas188nominais no relatório.
+
+| Consumidor/tipo | Prova de operação/perfil/persistência | Limite da prova |
+| --- | --- | --- |
+| Fundiário PDF |Upload privado→quarentena404→ClamDreal/hash→owner200→original canónico cifrado recuperado por bytes; outro/manager404; GETestado; impressão props200; tamper404; leitura auditada.|IndependentDocumentOperationsTest, iterador próprioPDF; não PDFrenderizado/browser18097.|
+| Fundiário PNG |Mesmo percurso, iteradorPNGreal; bytes/hash/scan próprios e size_bytes/uploaded_by.|Não prova renderização visual.|
+| Fundiário JPEG |Mesmo percurso, iteradorJPEGreal; bytes/hash/scan próprios e permissões.|Não prova qualquer conversão/derivada não executada.|
+| Sala parceria PDF |Autor200/candidato404→partilha autoria persistida→candidato200→novo contexto auth/GETlista→revogação404; candidato não partilha403; gestor/estranho403; scan originalreal/tamper404.|Método próprio com iteradorPDF; novo contexto de autenticação em teste, não sessão nova de navegador.|
+| Sala parceria PNG |Mesmo percurso, iteradorPNGreal, partilha/revogação/eventos próprios, original cifrado preservado.|Interface da sala pendente.|
+| Sala parceria JPEG |Mesmo percurso, iteradorJPEGreal, original/hash/scan próprios.|Não certifica acordo jurídico externo nem todos os anexos existentes.|
+| Lote biblioteca PDF |ImportDocumentBatchTest::test_qa_batch_real_scan_preserves_original_replay_identity_conflict_and_profile_guards: actorQAsem permissão/ambiente ativo recusados; bytes duplicados→um original privado; ClamDreal; gestor200/público 404; replay 0 novos; conflito mesma identidade/bytes diferentes não substitui original.|CLIQA, não mecanismo autenticado de aplicação ativa. Dois testes antigos do ficheiro usam fixture/Busfake.|
+| Oportunidades PDF/PNG/3WebP |resources-real-http-qa.json renovado: novo PDF válido→upload/scan/download/logout/nova sessão/403outra conta. resource-originals-preservation-http-qa.json preserva5binários anteriores e confirma uma página do novo PDF baixado; PNG/3WebP assinados recuperados.|Novo scan real somente do novo PDF; scans das derivadas anteriores conservados. Nenhum ensaio visual.|
+| Biblioteca/Balcão |document-consumers-real-qa.xml e provas anteriores de bytes/MIME/CSP/scan/perfil conservadas; ensaio de loteQA deste lote separado.|PDFview bytes/CSP não é renderização, nem demonstra validade de todos os fixtures antigos.|
+
+Fundiário e parceria agora reutilizam VerifiedDocumentBinary, sem relaxar permissões nem duplicar documents. Nenhum original foi convertido em cópia pública; novos uploads registam autor/tamanho. Document-independent-qa.xml e document-batch-independent-qa.xml distinguem scanner real de fixture. Arranque permanente ClamD/assinaturas/GDativo permanecem separados das operações demonstradas.
+
+**C41 — validade de PDF também é critério próprio:** os novos testes fundiário/parceria/lote utilizam SyntheticDocument::pdf, parseado por ferramenta independente (document-types-fixture-qa.json: uma página/texto). O placeholder PDF histórico09/10 só tinha cabeçalho/terminador: seus scans/hashes são provas de bytes, não de legibilidade. Sem substituí-lo, resources-real-http-qa.json agora demonstra um novo PDF válido no servidor 18097 (upload/ClamD/download/logout/nova sessão/403outra conta). resource-originals-preservation-http-qa.json recupera os 5binários anteriores por hash e parseia o novo PDF baixado. PNG/3WebP assinados recuperados outra vez, mas scans das derivadas são os anteriores, sem novo scan inventado. Renderização do novo PDF continua pendente.
+
+**C42 — credenciaisQA:** dois atores auxiliares do script antigo tinham passwords fixas que apareceram na leitura do código; foram rodadas apenas na baseQA, remember tokens revogados e valores fixos retirados do script. Nenhuma sessão alvo restante encontrada para apagar. MFA e a linha inteira da conta 18 preservados; chave/configuração ativa não alteradas. resource-http-actors-rotation-qa.json contém somente contagens/flags, sem passwords/cookies/OTP.
+
+Workflow/contratos:110defs/9 contratos normativos preparados, runtime_validation_implemented=false/workflow_implemented=false/qa_activation=false; não existe percurso completo novo a certificar. Roteiros 19 etapas/5fases conservados. Provas e contagens da matriz em relatorio-executivo.md.
+
+
+**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores. 361 e2/39/179 são a baseline 09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.
+
+
## C37 — MFA QA recuperado; cenário A visual por retomar
**C37/P0 — falha bloqueante do cenário A reportada pelo utilizador, corrigida por código/HTTP/persistência QA; retoma visual ainda pendente.** URL: http://127.0.0.1:18097/investimentos. Alvo real confirmado antes de qualquer escrita: `desk_restore_20261009_174726_test:55441`.
diff --git a/docs/investmoz/v2/auditoria-portal/correspondencias-cartograficas.md b/docs/investmoz/v2/auditoria-portal/correspondencias-cartograficas.md
index 33d0820f..086bc07a 100644
--- a/docs/investmoz/v2/auditoria-portal/correspondencias-cartograficas.md
+++ b/docs/investmoz/v2/auditoria-portal/correspondencias-cartograficas.md
@@ -1,3 +1,446 @@
+# Correspondências cartográficas — estado atual e histórico
+
+
+## Correspondências atuais — v2
+
+Esperado refere o exemplar aceite INE/UNOCHA07/06/2019, não uma certificação da divisão atual. Fonte oficial continua aceite. Nome/pai/edição são problemas de correspondência, não revalidação da credibilidade.
+
+| Nível | Esperado | Resolvido QA | Pendente | Incremento deste lote |
+| --- | ---: | ---: | ---: | ---: |
+| Províncias |11|11|0|0|
+| Distritos |159|133|26|5|
+| Postos administrativos |411|264|147|10|
+| Total |581|408|173|15|
+
+Baseline anterior393/188 mantida nohistórico. As antigas2/39/179 eram a situação09/10; não descrevem oestadoatual. Cadastro do seletor1920referências (11+148+437+1324),mais70países;geometria eapresentação funcional têm denominadores próprios. Semgeometriasdelocalidades/parcelas desteexemplar.
+
+Cinco aliasesdedistritos: **Cahora Bassa→CAHORA-BASSA;Ngauma→N`GAUMA;Ilha De Moçambique→CIDADE ILHA DE MOCAMBIQUE;Maxixe→CIDADE DE MAXIXE;Nacala-A-Velha→NACALA-VELHA**. Postos exatos pelospais:Chitima,Covo,Ilha De Moçambique,Itepela,Lumbo,Massangulo,Songo;aliasesapóstrofo:M'Sawize→M`SAWIZE,N'Cumpe→NCUMPE,N'Gapa→N`GAPA. Fonte,código,pai ecadastro existentes conferidos pela prévia;fundamento ehash emconfig/geometry-correspondences.phpv2 eprovaHTTP. Semrenomeação oualteraçãohierárquica.
+
+geometry-crosswalk-v2-http-qa.json:15 inseridos / 393 reutilizados,replayigual e15 limites recuperadospelaAPI domapa;sempublicação/sem demonstração visual. geometry-crosswalk-v2-preservation-qa.json:1.990 cadastros/361 originaispreservados e47 incrementais privados. Reversão existente não apaga originais;atualizaçãousada recusada. Mandie continua ambíguo entre2cadastros/códigos sobGuro;CidadeDeMaputoagregado nãoequivalea1distritourbano. Novosdistritos/edições nãoassociadosporproximidade.
+
+### Distritos — 26 lacunas por nome
+
+| Código | Nome | Província / pai | Causa |
+| --- | --- | --- | --- |
+|MZ0801|Chimbonila|Niassa / Niassa|Nome sem correspondência única sob o pai resolvido|
+|MZ0206|Chongoene|Gaza / Gaza|Nome sem correspondência única sob o pai resolvido|
+|MZ0601|Cidade De Maputo|Maputo City / Maputo City|Nome sem correspondência única sob o pai resolvido|
+|MZ1104|Derre|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ1007|Doa|Tete / Tete|Nome sem correspondência única sob o pai resolvido|
+|MZ0703|Erati|Nampula / Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ0804|Ilha Licom|Niassa / Niassa|Nome sem correspondência única sob o pai resolvido|
+|MZ0805|Ilha Risunodo|Niassa / Niassa|Nome sem correspondência única sob o pai resolvido|
+|MZ0807|Lago Niassa|Niassa / Niassa|Nome sem correspondência única sob o pai resolvido|
+|MZ0706|Larde|Nampula / Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ0209|Limpopo|Gaza / Gaza|Nome sem correspondência única sob o pai resolvido|
+|MZ0707|Liúpo|Nampula / Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ1109|Luabo|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ0405|Macate|Manica / Manica|Nome sem correspondência única sob o pai resolvido|
+|MZ0211|Mandlakaze|Gaza / Gaza|Nome sem correspondência única sob o pai resolvido|
+|MZ0212|Mapai|Gaza / Gaza|Nome sem correspondência única sob o pai resolvido|
+|MZ1112|Maquival|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ1010|Marara|Tete / Tete|Nome sem correspondência única sob o pai resolvido|
+|MZ0109|Metuge|Cabo Delgado / Cabo Delgado|Nome sem correspondência única sob o pai resolvido|
+|MZ1115|Mocubela|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ1116|Molumbo|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ1119|Mulevala|Zambezia / Zambezia|Nome sem correspondência única sob o pai resolvido|
+|MZ0719|Nacala|Nampula / Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ0722|Rapale|Nampula / Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ0412|Vanduzi|Manica / Manica|Nome sem correspondência única sob o pai resolvido|
+|MZ1015|Zumbu|Tete / Tete|Nome sem correspondência única sob o pai resolvido|
+
+### Postos — 147 lacunas por nome
+
+| Código | Nome | Província / pai | Causa |
+| --- | --- | --- | --- |
+|MZ110101|Alto Molocue|Zambezia / Alto Molocue|Nome sem correspondência única sob o pai resolvido|
+|MZ070301|Alua|Nampula / Erati|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ072201|Anchilo|Nampula / Rapale|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ070101|Angoche|Nampula / Angoche|Nome sem correspondência única sob o pai resolvido|
+|MZ111501|Bajone|Zambezia / Mocubela|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ041101|Bazua|Manica / Tambara|Nome sem correspondência única sob o pai resolvido|
+|MZ070103|Boila|Nampula / Angoche|Nome sem correspondência única sob o pai resolvido|
+|MZ090201|Caia|Sofala / Caia|Nome sem correspondência única sob o pai resolvido|
+|MZ020801|Caniçado|Gaza / Guija|Nome sem correspondência única sob o pai resolvido|
+|MZ101301|Charre|Tete / Mutarara|Nome sem correspondência única sob o pai resolvido|
+|MZ021101|Chibonzane|Gaza / Mandlakaze|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020204|Chibuto|Gaza / Chibuto|Nome sem correspondência única sob o pai resolvido|
+|MZ020901|Chicumbane|Gaza / Limpopo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ021102|Chidenguele|Gaza / Mandlakaze|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020401|Chigubo|Gaza / Chigubo|Nome sem correspondência única sob o pai resolvido|
+|MZ080101|Chimbonila|Niassa / Chimbonila|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ110201|Chinde|Zambezia / Chinde|Nome sem correspondência única sob o pai resolvido|
+|MZ100201|Chintholo|Tete / Cahora Bassa|Nome sem correspondência única sob o pai resolvido|
+|MZ100901|Chinthopo|Tete / Magoe|Nome sem correspondência única sob o pai resolvido|
+|MZ100301|Chipembere|Tete / Changara|Nome sem correspondência única sob o pai resolvido|
+|MZ101102|Chiputu|Tete / Maravia|Nome sem correspondência única sob o pai resolvido|
+|MZ020902|Chissano|Gaza / Limpopo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ040601|Chitobe|Manica / Machaze|Nome sem correspondência única sob o pai resolvido|
+|MZ010301|Chiure|Cabo Delgado / Chiure|Nome sem correspondência única sob o pai resolvido|
+|MZ020501|Chokwe|Gaza / Chokwe|Nome sem correspondência única sob o pai resolvido|
+|MZ020601|Chongoene|Gaza / Chongoene|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ090601|Cidade Da Beira|Sofala / Cidade Da Beira|Nome sem correspondência única sob o pai resolvido|
+|MZ050201|Cidade Da Matola|Maputo / Cidade Da Matola|Nome sem correspondência única sob o pai resolvido|
+|MZ040201|Cidade De Chimoio|Manica / Cidade De Chimoio|Nome sem correspondência única sob o pai resolvido|
+|MZ030101|Cidade De Inhambane|Inhambane / Cidade De Inhambane|Nome sem correspondência única sob o pai resolvido|
+|MZ080201|Cidade De Lichinga|Niassa / Cidade De Lichinga|Nome sem correspondência única sob o pai resolvido|
+|MZ060101|Cidade De Maputo|Maputo City / Cidade De Maputo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ070201|Cidade De Nampula|Nampula / Cidade De Nampula|Nome sem correspondência única sob o pai resolvido|
+|MZ010401|Cidade De Pemba|Cabo Delgado / Cidade De Pemba|Nome sem correspondência única sob o pai resolvido|
+|MZ100601|Cidade De Tete|Tete / Cidade De Tete|Nome sem correspondência única sob o pai resolvido|
+|MZ080301|Cuamba|Niassa / Cuamba|Nome sem correspondência única sob o pai resolvido|
+|MZ110401|Derre|Zambezia / Derre|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020402|Dindiza|Gaza / Chigubo|Nome sem correspondência única sob o pai resolvido|
+|MZ100701|Doa|Tete / Doa|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ090701|Dondo|Sofala / Dondo|Nome sem correspondência única sob o pai resolvido|
+|MZ080302|Etarara|Niassa / Cuamba|Nome sem correspondência única sob o pai resolvido|
+|MZ090801|Gorongosa|Sofala / Gorongosa|Nome sem correspondência única sob o pai resolvido|
+|MZ040401|Guro|Manica / Guro|Nome sem correspondência única sob o pai resolvido|
+|MZ110601|Gurue|Zambezia / Gurue|Nome sem correspondência única sob o pai resolvido|
+|MZ030401|Homoine|Inhambane / Homoine|Nome sem correspondência única sob o pai resolvido|
+|MZ010501|Ibo|Cabo Delgado / Ibo|Nome sem correspondência única sob o pai resolvido|
+|MZ080401|Ilha Licom|Niassa / Ilha Licom|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ080501|Ilha Risunodo|Niassa / Ilha Risunodo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ011202|Imbuo|Cabo Delgado / Mueda|Nome sem correspondência única sob o pai resolvido|
+|MZ030501|Inharrime|Inhambane / Inharrime|Nome sem correspondência única sob o pai resolvido|
+|MZ110802|Inhassunge|Zambezia / Inhassunge|Nome sem correspondência única sob o pai resolvido|
+|MZ071302|Iuluti|Nampula / Mogovolas|Nome sem correspondência única sob o pai resolvido|
+|MZ101201|Kambulatsisi|Tete / Moatize|Nome sem correspondência única sob o pai resolvido|
+|MZ010203|Kuekue|Cabo Delgado / Balama|Nome sem correspondência única sob o pai resolvido|
+|MZ080701|Lago Niassa|Niassa / Lago Niassa|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ070501|Lalaua|Nampula / Lalaua|Nome sem correspondência única sob o pai resolvido|
+|MZ070601|Larde|Nampula / Larde|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ080102|Lione|Niassa / Chimbonila|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ070701|Liúpo|Nampula / Liúpo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ110901|Luabo|Zambezia / Luabo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ081901|Lussimbesse|Niassa / Sanga|Nome sem correspondência única sob o pai resolvido|
+|MZ011501|M'Tamba|Cabo Delgado / Nangade|Nome sem correspondência única sob o pai resolvido|
+|MZ021002|Mabalane|Gaza / Mabalane|Nome sem correspondência única sob o pai resolvido|
+|MZ040501|Macate|Manica / Macate|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020101|Macia|Gaza / Bilene|Nome sem correspondência única sob o pai resolvido|
+|MZ010602|Macomia|Cabo Delgado / Macomia|Nome sem correspondência única sob o pai resolvido|
+|MZ021103|Macuacua|Gaza / Mandlakaze|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ112001|Macuze|Zambezia / Namacurra|Nome sem correspondência única sob o pai resolvido|
+|MZ020602|Madzucane|Gaza / Chongoene|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ111101|Maganja|Zambezia / Maganja Da Costa|Nome sem correspondência única sob o pai resolvido|
+|MZ020102|Makluane|Gaza / Bilene|Nome sem correspondência única sob o pai resolvido|
+|MZ080801|Malanga|Niassa / Majune|Nome sem correspondência única sob o pai resolvido|
+|MZ070802|Malema|Nampula / Malema|Nome sem correspondência única sob o pai resolvido|
+|MZ101104|Malowera|Tete / Maravia|Nome sem correspondência única sob o pai resolvido|
+|MZ040402|Mandie|Manica / Guro|Múltiplos cadastros sob o mesmo pai; preservar ambos|
+|MZ080901|Mandimba|Niassa / Mandimba|Nome sem correspondência única sob o pai resolvido|
+|MZ021104|Mandlakaze|Gaza / Mandlakaze|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ050404|Manhiça|Maputo / Manhiça|Nome sem correspondência única sob o pai resolvido|
+|MZ040802|Manica|Manica / Manica|Nome sem correspondência única sob o pai resolvido|
+|MZ021201|Mapai|Gaza / Mapai|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ111201|Maquival|Zambezia / Maquival|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ101001|Marara|Tete / Marara|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ081002|Marrupa|Niassa / Marrupa|Nome sem correspondência única sob o pai resolvido|
+|MZ041201|Matsinho|Manica / Vanduzi|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ081202|Mavago|Niassa / Mavago|Nome sem correspondência única sob o pai resolvido|
+|MZ031001|Maxixe|Inhambane / Maxixe|Nome sem correspondência única sob o pai resolvido|
+|MZ071103|Mazula|Nampula / Memba|Nome sem correspondência única sob o pai resolvido|
+|MZ081402|Mecula|Niassa / Mecula|Nome sem correspondência única sob o pai resolvido|
+|MZ080103|Meponda|Niassa / Chimbonila|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ110603|Mepuagiua|Zambezia / Gurue|Nome sem correspondência única sob o pai resolvido|
+|MZ010102|Mesa|Cabo Delgado / Ancuabe|Nome sem correspondência única sob o pai resolvido|
+|MZ080604|Metangula|Niassa / Lago|Nome sem correspondência única sob o pai resolvido|
+|MZ010901|Metuge|Cabo Delgado / Metuge|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ110202|Micaune|Zambezia / Chinde|Nome sem correspondência única sob o pai resolvido|
+|MZ010902|Mieze|Cabo Delgado / Metuge|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ111401|Mocuba|Zambezia / Mocuba|Nome sem correspondência única sob o pai resolvido|
+|MZ111502|Mocubela|Zambezia / Mocubela|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ030502|Mocumbi|Inhambane / Inharrime|Nome sem correspondência única sob o pai resolvido|
+|MZ111601|Molumbo|Zambezia / Molumbo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ071402|Moma|Nampula / Moma|Nome sem correspondência única sob o pai resolvido|
+|MZ071502|Monapo|Nampula / Monapo|Nome sem correspondência única sob o pai resolvido|
+|MZ011103|Montepuez|Cabo Delgado / Montepuez|Nome sem correspondência única sob o pai resolvido|
+|MZ071603|Mossuril|Nampula / Mossuril|Nome sem correspondência única sob o pai resolvido|
+|MZ100902|Mphende|Tete / Magoe|Nome sem correspondência única sob o pai resolvido|
+|MZ100402|Mualadze|Tete / Chifunde|Nome sem correspondência única sob o pai resolvido|
+|MZ112301|Mualama|Zambezia / Pebane|Nome sem correspondência única sob o pai resolvido|
+|MZ031102|Mucoduene|Inhambane / Morrumbene|Nome sem correspondência única sob o pai resolvido|
+|MZ070602|Mucuali|Nampula / Larde|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ071702|Muculoene|Nampula / Muecate|Nome sem correspondência única sob o pai resolvido|
+|MZ011203|Mueda|Cabo Delgado / Mueda|Nome sem correspondência única sob o pai resolvido|
+|MZ050603|Mugazine|Maputo / Matutuine|Nome sem correspondência única sob o pai resolvido|
+|MZ111901|Mulevala|Zambezia / Mulevala|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ041002|Muoha|Manica / Sussundenga|Nome sem correspondência única sob o pai resolvido|
+|MZ072202|Mutivasse|Nampula / Rapale|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ101501|Muze|Tete / Zumbu|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ071901|Nacala|Nampula / Nacala|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ072002|Nacala-A-Velha|Nampula / Nacala-A-Velha|Nome sem correspondência única sob o pai resolvido|
+|MZ072203|Namaita|Nampula / Rapale|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ111403|Namanjavira|Zambezia / Mocuba|Nome sem correspondência única sob o pai resolvido|
+|MZ070302|Namapa|Nampula / Erati|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ071304|Nametil|Nampula / Mogovolas|Nome sem correspondência única sob o pai resolvido|
+|MZ071201|Namige|Nampula / Mogincual|Nome sem correspondência única sob o pai resolvido|
+|MZ070303|Namiroa|Nampula / Erati|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ011405|Namuno|Cabo Delgado / Namuno|Nome sem correspondência única sob o pai resolvido|
+|MZ071305|Nanhupo Rio|Nampula / Mogovolas|Nome sem correspondência única sob o pai resolvido|
+|MZ050604|Ndelane|Maputo / Matutuine|Nome sem correspondência única sob o pai resolvido|
+|MZ020603|Nguzene|Gaza / Chongoene|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ090802|Nhamadze|Sofala / Gorongosa|Nome sem correspondência única sob o pai resolvido|
+|MZ040703|Nhamagua|Manica / Macossa|Nome sem correspondência única sob o pai resolvido|
+|MZ112201|Nicoadala|Zambezia / Nicoadala|Nome sem correspondência única sob o pai resolvido|
+|MZ100403|Nsadzu|Tete / Chifunde|Nome sem correspondência única sob o pai resolvido|
+|MZ101401|Ntengo-Wa-Mbalame|Tete / Tsangano|Nome sem correspondência única sob o pai resolvido|
+|MZ011601|Olumbi|Cabo Delgado / Palma|Nome sem correspondência única sob o pai resolvido|
+|MZ050405|Palmeira|Maputo / Manhiça|Nome sem correspondência única sob o pai resolvido|
+|MZ070702|Quinga|Nampula / Liúpo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ072204|Rapale|Nampula / Rapale|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ090103|Sofala|Sofala / Buzi|Nome sem correspondência única sob o pai resolvido|
+|MZ091003|Subwe|Sofala / Maringue|Nome sem correspondência única sob o pai resolvido|
+|MZ100102|Ulongue|Tete / Angonia|Nome sem correspondência única sob o pai resolvido|
+|MZ081904|Unango|Niassa / Sanga|Nome sem correspondência única sob o pai resolvido|
+|MZ041202|Vanduzi|Manica / Vanduzi|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020302|Vila Eduardo Mondlane|Gaza / Chicualacuala|Nome sem correspondência única sob o pai resolvido|
+|MZ021105|Xhalala|Gaza / Mandlakaze|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ101502|Zambue|Tete / Zumbu|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ040502|Zembe|Manica / Macate|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ020903|Zongoene|Gaza / Limpopo|Pai ainda sem correspondência; não associar por nome isolado|
+|MZ101503|Zumbu|Tete / Zumbu|Pai ainda sem correspondência; não associar por nome isolado|
+
+**Visual pendente:**cada seletor/país/origem/mapa por formulário, gravação erecuperação;408 APIs não demonstram render. Todas as fontes, nomes e contagens anteriores seguem abaixo como história.
+
+
+10/10/2026. Complemento de AUD-GEO-02/03 na mesma matriz. QA18097/desk_restore_20261009_174726_test:55441. Esperado refere o exemplar INE/UNOCHA de07/06/2019 aceite, não uma divisão administrativa atual certificada.
+
+| Nível | Esperado | Resolvido QA | Pendente | Incremento sobre09/10 |
+| --- | ---: | ---: | ---: | ---: |
+| Províncias | 11 | 11 | 0 | +2 |
+| Distritos | 159 | 128 | 31 | +8 |
+| Postos administrativos | 411 | 254 | 157 | +22 |
+
+**393 resolvidos/188 pendentes, de 581 elementos.** As 32 novas geometrias são 2+8+22; as 361 anteriores e os 1990 registos territoriais foram preservados no retrato. O seletor recupera 1920 referências de quatro níveis:11+148+437+1324; os 70 países do cadastro não integram esse denominador. Sem geometrias de localidades neste exemplar. Cadastro, geometria autorizada e apresentação funcional são critérios independentes.
+
+## Correspondências explícitas
+
+| INE | Nome do exemplar | Cadastro/código | ID existente | Fundamento |
+| --- | --- | --- | --- | --- |
+| MZ05 | Maputo | Maputo Província/10 | bfde2651-2b46-5d9c-a500-733fa55a8c5c | INE ADM1 MZ05 designa a província Maputo; o exemplar separa Maputo City MZ06. Cadastro cartografia_moz.xlsx: Provincia Maputo Província, código10, sob Moçambique. Códigos10 e MZ05 pertencem a sistemas distintos. |
+| MZ06 | Maputo City | Maputo Cidade/11 | 4aa31470-997e-5c63-8fe0-ff2f62586f56 | INE ADM1 MZ06 designa Maputo City, distinta da província MZ05; tradução explícita City/Cidade. Cadastro cartografia_moz.xlsx: Provincia Maputo Cidade, código11, sob Moçambique. Não associa distritos urbanos ao distrito agregado da ediçãoINE. |
+| MZ0502 | Cidade Da Matola | CIDADE DE MATOLA/01 | 9e89eff2-8fe7-5c3f-bedc-29ba03e2db0e | Variação explícita da preposição Da/DE em Cidade de Matola. INE ADM2 MZ0502 sob Maputo MZ05; cadastro cartografia_moz.xlsx Distrito CIDADE DE MATOLA, código01 sob Maputo Província. Exige pai previamente correspondido; não altera limites ou hierarquia. |
+
+Configuração versionada config/geometry-correspondences.php; fonte/hash/edição/nome/código/pai entram na prévia assinada. CódigosINE e workbook não são convertidos aritmeticamente. Zero renomeações, novos territórios, mudanças de pai ou publicação. Cidade De Maputo/MZ0601 é agregado de2019: não se associa a um dos distritos urbanos cadastrados.
+
+## Mandie — ambiguidade preservada
+
+MZ040402/Mandie sob Guro tem candidatos4944a651-23ec-5d51-a5ff-14b0b53ed672 (source_code02) e ea7be18f-2a93-5416-a07a-c207a700e070 (03). Workbook aceite:MANDIE nas linhas11117 e11138, códigos diferentes. Sufixo do P-code não prova equivalência de códigos. Conferir correspondência documental específica; não fundir cadastros. Não bloqueia correspondentes únicos independentes.
+
+## Províncias — 0 pendentes atuais
+
+| Código | Nome exato | Pai | Causa |
+| --- | --- | --- | --- |
+
+## Distritos — 31 pendentes atuais
+
+| Código | Nome exato | Pai | Causa |
+| --- | --- | --- | --- |
+| MZ1002 | Cahora Bassa | Tete | Nome sem correspondência única sob o pai resolvido |
+| MZ0801 | Chimbonila | Niassa | Nome sem correspondência única sob o pai resolvido |
+| MZ0206 | Chongoene | Gaza | Nome sem correspondência única sob o pai resolvido |
+| MZ0601 | Cidade De Maputo | Maputo City | Nome sem correspondência única sob o pai resolvido |
+| MZ1104 | Derre | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ1007 | Doa | Tete | Nome sem correspondência única sob o pai resolvido |
+| MZ0703 | Erati | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0704 | Ilha De Moçambique | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0804 | Ilha Licom | Niassa | Nome sem correspondência única sob o pai resolvido |
+| MZ0805 | Ilha Risunodo | Niassa | Nome sem correspondência única sob o pai resolvido |
+| MZ0807 | Lago Niassa | Niassa | Nome sem correspondência única sob o pai resolvido |
+| MZ0706 | Larde | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0209 | Limpopo | Gaza | Nome sem correspondência única sob o pai resolvido |
+| MZ0707 | Liúpo | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ1109 | Luabo | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ0405 | Macate | Manica | Nome sem correspondência única sob o pai resolvido |
+| MZ0211 | Mandlakaze | Gaza | Nome sem correspondência única sob o pai resolvido |
+| MZ0212 | Mapai | Gaza | Nome sem correspondência única sob o pai resolvido |
+| MZ1112 | Maquival | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ1010 | Marara | Tete | Nome sem correspondência única sob o pai resolvido |
+| MZ0310 | Maxixe | Inhambane | Nome sem correspondência única sob o pai resolvido |
+| MZ0109 | Metuge | Cabo Delgado | Nome sem correspondência única sob o pai resolvido |
+| MZ1115 | Mocubela | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ1116 | Molumbo | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ1119 | Mulevala | Zambezia | Nome sem correspondência única sob o pai resolvido |
+| MZ0719 | Nacala | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0720 | Nacala-A-Velha | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0817 | Ngauma | Niassa | Nome sem correspondência única sob o pai resolvido |
+| MZ0722 | Rapale | Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ0412 | Vanduzi | Manica | Nome sem correspondência única sob o pai resolvido |
+| MZ1015 | Zumbu | Tete | Nome sem correspondência única sob o pai resolvido |
+
+## Postos administrativos — 157 pendentes atuais
+
+| Código | Nome exato | Pai | Causa |
+| --- | --- | --- | --- |
+| MZ110101 | Alto Molocue | Alto Molocue | Nome sem correspondência única sob o pai resolvido |
+| MZ070301 | Alua | Erati | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ072201 | Anchilo | Rapale | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ070101 | Angoche | Angoche | Nome sem correspondência única sob o pai resolvido |
+| MZ111501 | Bajone | Mocubela | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ041101 | Bazua | Tambara | Nome sem correspondência única sob o pai resolvido |
+| MZ070103 | Boila | Angoche | Nome sem correspondência única sob o pai resolvido |
+| MZ090201 | Caia | Caia | Nome sem correspondência única sob o pai resolvido |
+| MZ020801 | Caniçado | Guija | Nome sem correspondência única sob o pai resolvido |
+| MZ101301 | Charre | Mutarara | Nome sem correspondência única sob o pai resolvido |
+| MZ021101 | Chibonzane | Mandlakaze | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020204 | Chibuto | Chibuto | Nome sem correspondência única sob o pai resolvido |
+| MZ020901 | Chicumbane | Limpopo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ021102 | Chidenguele | Mandlakaze | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020401 | Chigubo | Chigubo | Nome sem correspondência única sob o pai resolvido |
+| MZ080101 | Chimbonila | Chimbonila | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ110201 | Chinde | Chinde | Nome sem correspondência única sob o pai resolvido |
+| MZ100201 | Chintholo | Cahora Bassa | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ100901 | Chinthopo | Magoe | Nome sem correspondência única sob o pai resolvido |
+| MZ100301 | Chipembere | Changara | Nome sem correspondência única sob o pai resolvido |
+| MZ101102 | Chiputu | Maravia | Nome sem correspondência única sob o pai resolvido |
+| MZ020902 | Chissano | Limpopo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ100202 | Chitima | Cahora Bassa | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ040601 | Chitobe | Machaze | Nome sem correspondência única sob o pai resolvido |
+| MZ010301 | Chiure | Chiure | Nome sem correspondência única sob o pai resolvido |
+| MZ020501 | Chokwe | Chokwe | Nome sem correspondência única sob o pai resolvido |
+| MZ020601 | Chongoene | Chongoene | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ090601 | Cidade Da Beira | Cidade Da Beira | Nome sem correspondência única sob o pai resolvido |
+| MZ050201 | Cidade Da Matola | Cidade Da Matola | Nome sem correspondência única sob o pai resolvido |
+| MZ040201 | Cidade De Chimoio | Cidade De Chimoio | Nome sem correspondência única sob o pai resolvido |
+| MZ030101 | Cidade De Inhambane | Cidade De Inhambane | Nome sem correspondência única sob o pai resolvido |
+| MZ080201 | Cidade De Lichinga | Cidade De Lichinga | Nome sem correspondência única sob o pai resolvido |
+| MZ060101 | Cidade De Maputo | Cidade De Maputo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ070201 | Cidade De Nampula | Cidade De Nampula | Nome sem correspondência única sob o pai resolvido |
+| MZ010401 | Cidade De Pemba | Cidade De Pemba | Nome sem correspondência única sob o pai resolvido |
+| MZ100601 | Cidade De Tete | Cidade De Tete | Nome sem correspondência única sob o pai resolvido |
+| MZ072001 | Covo | Nacala-A-Velha | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ080301 | Cuamba | Cuamba | Nome sem correspondência única sob o pai resolvido |
+| MZ110401 | Derre | Derre | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020402 | Dindiza | Chigubo | Nome sem correspondência única sob o pai resolvido |
+| MZ100701 | Doa | Doa | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ090701 | Dondo | Dondo | Nome sem correspondência única sob o pai resolvido |
+| MZ080302 | Etarara | Cuamba | Nome sem correspondência única sob o pai resolvido |
+| MZ090801 | Gorongosa | Gorongosa | Nome sem correspondência única sob o pai resolvido |
+| MZ040401 | Guro | Guro | Nome sem correspondência única sob o pai resolvido |
+| MZ110601 | Gurue | Gurue | Nome sem correspondência única sob o pai resolvido |
+| MZ030401 | Homoine | Homoine | Nome sem correspondência única sob o pai resolvido |
+| MZ010501 | Ibo | Ibo | Nome sem correspondência única sob o pai resolvido |
+| MZ070401 | Ilha De Moçambique | Ilha De Moçambique | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ080401 | Ilha Licom | Ilha Licom | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ080501 | Ilha Risunodo | Ilha Risunodo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ011202 | Imbuo | Mueda | Nome sem correspondência única sob o pai resolvido |
+| MZ030501 | Inharrime | Inharrime | Nome sem correspondência única sob o pai resolvido |
+| MZ110802 | Inhassunge | Inhassunge | Nome sem correspondência única sob o pai resolvido |
+| MZ081701 | Itepela | Ngauma | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ071302 | Iuluti | Mogovolas | Nome sem correspondência única sob o pai resolvido |
+| MZ101201 | Kambulatsisi | Moatize | Nome sem correspondência única sob o pai resolvido |
+| MZ010203 | Kuekue | Balama | Nome sem correspondência única sob o pai resolvido |
+| MZ080701 | Lago Niassa | Lago Niassa | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ070501 | Lalaua | Lalaua | Nome sem correspondência única sob o pai resolvido |
+| MZ070601 | Larde | Larde | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ080102 | Lione | Chimbonila | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ070701 | Liúpo | Liúpo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ110901 | Luabo | Luabo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ070402 | Lumbo | Ilha De Moçambique | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ081901 | Lussimbesse | Sanga | Nome sem correspondência única sob o pai resolvido |
+| MZ081201 | M'Sawize | Mavago | Nome sem correspondência única sob o pai resolvido |
+| MZ011501 | M'Tamba | Nangade | Nome sem correspondência única sob o pai resolvido |
+| MZ021002 | Mabalane | Mabalane | Nome sem correspondência única sob o pai resolvido |
+| MZ040501 | Macate | Macate | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020101 | Macia | Bilene | Nome sem correspondência única sob o pai resolvido |
+| MZ010602 | Macomia | Macomia | Nome sem correspondência única sob o pai resolvido |
+| MZ021103 | Macuacua | Mandlakaze | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ112001 | Macuze | Namacurra | Nome sem correspondência única sob o pai resolvido |
+| MZ020602 | Madzucane | Chongoene | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ111101 | Maganja | Maganja Da Costa | Nome sem correspondência única sob o pai resolvido |
+| MZ020102 | Makluane | Bilene | Nome sem correspondência única sob o pai resolvido |
+| MZ080801 | Malanga | Majune | Nome sem correspondência única sob o pai resolvido |
+| MZ070802 | Malema | Malema | Nome sem correspondência única sob o pai resolvido |
+| MZ101104 | Malowera | Maravia | Nome sem correspondência única sob o pai resolvido |
+| MZ040402 | Mandie | Guro | Mais de um cadastro com mesmo nome/pai; ambos preservados |
+| MZ080901 | Mandimba | Mandimba | Nome sem correspondência única sob o pai resolvido |
+| MZ021104 | Mandlakaze | Mandlakaze | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ050404 | Manhiça | Manhiça | Nome sem correspondência única sob o pai resolvido |
+| MZ040802 | Manica | Manica | Nome sem correspondência única sob o pai resolvido |
+| MZ021201 | Mapai | Mapai | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ111201 | Maquival | Maquival | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ101001 | Marara | Marara | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ081002 | Marrupa | Marrupa | Nome sem correspondência única sob o pai resolvido |
+| MZ081702 | Massangulo | Ngauma | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ041201 | Matsinho | Vanduzi | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ081202 | Mavago | Mavago | Nome sem correspondência única sob o pai resolvido |
+| MZ031001 | Maxixe | Maxixe | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ071103 | Mazula | Memba | Nome sem correspondência única sob o pai resolvido |
+| MZ081402 | Mecula | Mecula | Nome sem correspondência única sob o pai resolvido |
+| MZ080103 | Meponda | Chimbonila | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ110603 | Mepuagiua | Gurue | Nome sem correspondência única sob o pai resolvido |
+| MZ010102 | Mesa | Ancuabe | Nome sem correspondência única sob o pai resolvido |
+| MZ080604 | Metangula | Lago | Nome sem correspondência única sob o pai resolvido |
+| MZ010901 | Metuge | Metuge | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ110202 | Micaune | Chinde | Nome sem correspondência única sob o pai resolvido |
+| MZ010902 | Mieze | Metuge | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ111401 | Mocuba | Mocuba | Nome sem correspondência única sob o pai resolvido |
+| MZ111502 | Mocubela | Mocubela | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ030502 | Mocumbi | Inharrime | Nome sem correspondência única sob o pai resolvido |
+| MZ111601 | Molumbo | Molumbo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ071402 | Moma | Moma | Nome sem correspondência única sob o pai resolvido |
+| MZ071502 | Monapo | Monapo | Nome sem correspondência única sob o pai resolvido |
+| MZ011103 | Montepuez | Montepuez | Nome sem correspondência única sob o pai resolvido |
+| MZ071603 | Mossuril | Mossuril | Nome sem correspondência única sob o pai resolvido |
+| MZ100902 | Mphende | Magoe | Nome sem correspondência única sob o pai resolvido |
+| MZ100402 | Mualadze | Chifunde | Nome sem correspondência única sob o pai resolvido |
+| MZ112301 | Mualama | Pebane | Nome sem correspondência única sob o pai resolvido |
+| MZ031102 | Mucoduene | Morrumbene | Nome sem correspondência única sob o pai resolvido |
+| MZ070602 | Mucuali | Larde | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ071702 | Muculoene | Muecate | Nome sem correspondência única sob o pai resolvido |
+| MZ011203 | Mueda | Mueda | Nome sem correspondência única sob o pai resolvido |
+| MZ050603 | Mugazine | Matutuine | Nome sem correspondência única sob o pai resolvido |
+| MZ111901 | Mulevala | Mulevala | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ041002 | Muoha | Sussundenga | Nome sem correspondência única sob o pai resolvido |
+| MZ072202 | Mutivasse | Rapale | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ101501 | Muze | Zumbu | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ011404 | N'Cumpe | Namuno | Nome sem correspondência única sob o pai resolvido |
+| MZ011204 | N'Gapa | Mueda | Nome sem correspondência única sob o pai resolvido |
+| MZ071901 | Nacala | Nacala | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ072002 | Nacala-A-Velha | Nacala-A-Velha | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ072203 | Namaita | Rapale | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ111403 | Namanjavira | Mocuba | Nome sem correspondência única sob o pai resolvido |
+| MZ070302 | Namapa | Erati | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ071304 | Nametil | Mogovolas | Nome sem correspondência única sob o pai resolvido |
+| MZ071201 | Namige | Mogincual | Nome sem correspondência única sob o pai resolvido |
+| MZ070303 | Namiroa | Erati | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ011405 | Namuno | Namuno | Nome sem correspondência única sob o pai resolvido |
+| MZ071305 | Nanhupo Rio | Mogovolas | Nome sem correspondência única sob o pai resolvido |
+| MZ050604 | Ndelane | Matutuine | Nome sem correspondência única sob o pai resolvido |
+| MZ020603 | Nguzene | Chongoene | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ090802 | Nhamadze | Gorongosa | Nome sem correspondência única sob o pai resolvido |
+| MZ040703 | Nhamagua | Macossa | Nome sem correspondência única sob o pai resolvido |
+| MZ112201 | Nicoadala | Nicoadala | Nome sem correspondência única sob o pai resolvido |
+| MZ100403 | Nsadzu | Chifunde | Nome sem correspondência única sob o pai resolvido |
+| MZ101401 | Ntengo-Wa-Mbalame | Tsangano | Nome sem correspondência única sob o pai resolvido |
+| MZ011601 | Olumbi | Palma | Nome sem correspondência única sob o pai resolvido |
+| MZ050405 | Palmeira | Manhiça | Nome sem correspondência única sob o pai resolvido |
+| MZ070702 | Quinga | Liúpo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ072204 | Rapale | Rapale | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ090103 | Sofala | Buzi | Nome sem correspondência única sob o pai resolvido |
+| MZ100203 | Songo | Cahora Bassa | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ091003 | Subwe | Maringue | Nome sem correspondência única sob o pai resolvido |
+| MZ100102 | Ulongue | Angonia | Nome sem correspondência única sob o pai resolvido |
+| MZ081904 | Unango | Sanga | Nome sem correspondência única sob o pai resolvido |
+| MZ041202 | Vanduzi | Vanduzi | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020302 | Vila Eduardo Mondlane | Chicualacuala | Nome sem correspondência única sob o pai resolvido |
+| MZ021105 | Xhalala | Mandlakaze | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ101502 | Zambue | Zumbu | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ040502 | Zembe | Macate | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ020903 | Zongoene | Limpopo | Pai do exemplar sem correspondência; não associa por nome isolado |
+| MZ101503 | Zumbu | Zumbu | Pai do exemplar sem correspondência; não associa por nome isolado |
+
+## Provas e critérios abertos
+
+- geometry-crosswalk-http-qa.json: aplicação autenticada/MFA, replay e API do mapa para22postos novos. A tentativa anterior aplicou2províncias+8distritos antes de parar na ambiguidadeMandie; recibos/eventos originais estão na prova de preservação. O tratamento foi corrigido para manter ambiguidades pendentes e importar as correspondências únicas.
+- geometry-crosswalk-preservation-qa.json: alvo guardado,393 internos,32novos,361anteriores/1990cadastros preservados. geometry-consumers-path-qa.json recupera393/393 por serviço READ ONLY e0limites privados públicos. Não é prova de publicação ou desenho.
+- geometry-crosswalk-consumers-http-qa.json: nova consulta dos 32 limites inseridos, pelo endpoint usado pelo componente, recupera 32 para gestor/MFA e nenhum para público; as duas províncias Maputo têm correspondência única por nome exato. Não aplicou outro lote e não demonstra renderização.
+- TerritoryFields e ProvinceSelect partilhados usam os mesmos IDs/endpoints/preview. ProvinceSelect exige nome exato/único; conserva texto histórico e explica ausência. TypeScript/build passam; seleção/gravação/recuperação e Leaflet por consumidor exigem interface.
+- Reversão recusa alteração/publicação/FK e descendentes ativos da edição. Ordem:postos→distritos→províncias, só lotes novos; originais/cadastros/histórico preservados. Identidades revertidas não são ressuscitadas por replay.
+
+## Histórico09/10 — nomes e contagens anteriores
+
# Correspondências cartográficas — lacunas por nome
Complemento de AUD-GEO-02/03 da mesma matriz. Exemplar INE/UNOCHA 07/06/2019 aceite; esperado significa total deste exemplar, não um total administrativo atual certificado. Não converte limites administrativos em disponibilidade de terra.
diff --git a/docs/investmoz/v2/auditoria-portal/demonstracao-dashboard-oportunidades.md b/docs/investmoz/v2/auditoria-portal/demonstracao-dashboard-oportunidades.md
new file mode 100644
index 00000000..2bb5bb9e
--- /dev/null
+++ b/docs/investmoz/v2/auditoria-portal/demonstracao-dashboard-oportunidades.md
@@ -0,0 +1,21 @@
+# Ensaio de Gestão de Oportunidades a partir do dashboard — C43
+
+**URL inicial exato:** http://127.0.0.1:18097/dashboard. Apenas QA: `desk_restore_20261009_174726_test:55441`. Usar o gestor sintético QA **17**, com o MFA já configurado. O gestor QA14 também está autorizado; QA13/18 são investidores e não recebem gestão. Não reutilizar credenciais da conta ativa13.
+
+Estado: código, respostas HTTP, persistência e assets QA demonstrados; **cliques e resultado renderizado ainda pendentes**. C37 e cenários A/B do investidor permanecem separados e abertos. Nenhuma credencial, cookie ou código MFA neste roteiro.
+
+1. Entrar normalmente como gestor QA17 e completar o seu MFA. Abrir o URL inicial. Esperado: “Gestão de Oportunidades” e “Nova oportunidade” no início do painel e na barra lateral; o menu “Painel da gestão” aponta `/dashboard`. “Dossiers e percursos” continua `/investidor`.
+2. Clicar **Gestão de Oportunidades**. Esperado: URL `/management/opportunities`, lista, pesquisa, filtros e ação “Nova oportunidade”. Não começar por acesso direto à rota para certificar a navegação.
+3. Clicar **Nova oportunidade**. Esperado: `/management/opportunities/create`, formulário sem registo selecionado. Indicar título sintético QA, razão com pelo menos20caracteres; deixar outros campos finais incompletos.
+4. Clicar **Guardar rascunho**. Esperado: feedback de gravação; URL `/management/opportunities/{ID}/edit`, referência/ID estáveis, estado rascunho; sem submissão, aprovação ou publicação. Registar ID/referência mostrados.
+5. Sair e abrir outra sessão do navegador. Entrar com o mesmo gestor e MFA; abrir novamente `/dashboard`, clicar gestão, pesquisar a referência e abrir o rascunho. Esperado: mesmoID e os valores guardados. Uma atualização da página mantém o registo.
+6. Alterar título, indicar razão e guardar. Voltar à lista, pesquisar e reabrir. Esperado: título atualizado e histórico, preservando ID e relações.
+7. No editor, indicar razão e confirmar a operação. Clicar **Arquivar**. Esperado: estado arquivado, botão Restaurar, edição bloqueada; filtro Arquivadas encontra o mesmo registo. Arquivar conserva o registo (`deleted_at=null`); **Excluir rascunho** é outra ação.
+8. Clicar **Restaurar** com razão/confirmação. Esperado: volta a rascunho, mesmoID/título/histórico, novamente editável; não passa a publicado. Atualizar a página e conferir recuperação.
+9. Sair. Noutra conta investidor QA, abrir `/dashboard`: os dois atalhos administrativos não aparecem. Tentar o URL do registo criado:403, sem gravação. Manter este ensaio independente da confirmação visualC37 da conta18.
+
+Registar por passo: URL final, perfil/ID da conta, rótulos visíveis, ID/referência da oportunidade, resultado esperado/observado e captura sanitizada. Se recolher rede, somente método/caminho/status/destino; omitir `Cookie`, `X-XSRF-TOKEN` e corpos de autenticação/MFA. Não enviar credenciais.
+
+Para recuperar o fixture já demonstrado por HTTP, pesquisar **oportunidade QA13**, referência `INV-MZ-GEN-8580797530641128`. É ID de oportunidade, distinto da conta13. O título termina em `edited`, estado draft e quatro eventos. A oportunidade QA14 é outro fixture, do primeiro adaptador imobiliário API; o formulário especializado ainda não está implementado.
+
+Lista completa derivada da mesma matriz, para gestores QA: http://127.0.0.1:18097/qa-auditoria/pedidos-abertos. Inclui3349pedidos abertos pesquisáveis, fonte/versões, lacuna e próxima ação porID; investidor403. [Matriz única](matriz-requisitos.csv), [relatório](relatorio-executivo.md), [backlog](backlog.md), [ativação/reversão](plano-ativacao.md).
diff --git a/docs/investmoz/v2/auditoria-portal/execucao-percurso-i1-i3.md b/docs/investmoz/v2/auditoria-portal/execucao-percurso-i1-i3.md
index d59deaf0..b1d59c9d 100644
--- a/docs/investmoz/v2/auditoria-portal/execucao-percurso-i1-i3.md
+++ b/docs/investmoz/v2/auditoria-portal/execucao-percurso-i1-i3.md
@@ -1,5 +1,162 @@
# Execução do percurso InvestMoz — I0 e I1–I3 em QA
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco é a evidência mais recente desta matriz; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Cobertura após perfis v1 — 10/10/2026
+
+I0–I3 permanecem em QA. Cinco fases e 19 etapas preservadas, sem renumeração. C37, A/B e C43 visuais continuam pendentes. A autorização organizacional reutiliza OpportunityManagement, Resources, Fortify e entidades existentes; nenhuma jornada educativa nova foi iniciada.
+
+- Interface: preparada e compilada, sem observação no navegador. Roteiro manual de perfis inclui acessos permitidos/negados; A/B preservam o roteiro existente.
+- API: links descobertos no dashboard, rascunho 15 recuperado noutra sessão, coedição 22 e negações por tipo/organização/múltiplos papéis. Seletores autorizados e geometria do Promotor funcionam; submissão integral permanece bloqueada por contrato incompleto.
+- Persistência: autor, ID, versão e histórico preservados; Cabo Delgado recuperada com o mesmo ID/nome. Pedido de Promotor, comprovativos, auditoria, revogação e dupla demonstrados nos escopos descritos.
+- Documentos: quatro comprovativos sintéticos com ClamD real e hash recuperável; não generalizar às operações restantes. Originais anteriores preservados em 18 tabelas.
+- Ativo: exclusivamente READ ONLY, sem instalação/flag de perfis. 020000 instalada; recursos/percurso ainda ausentes. Mesma matriz: 3.386 requisitos, 6.838 ocorrências.
+
+Coordenadores, pareceristas, suporte e recurso estão explicitamente mapeados na reconciliação. Filas, decisões, SLA e incidentes funcionais continuam parciais ou não implementados no backlog. 393 geometrias privadas QA não encerram a integração visual; permanecem 31 distritos/157 postos nomeados.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Continuação independente C43/C44 —10/10/2026
+
+QA exclusiva: http://127.0.0.1:18097, alvo real `desk_restore_20261009_174726_test:55441`. Ativo consultado por transação SQL READ ONLY; 0 escritas/instalações/publicações ativas. Cinco fases/19 etapas, 5 dossiers/95 etapas e 393 geometrias QA preservados. C37 e aceitação visual permanecem abertos.
+
+Gestores QA 14/17 têm email verificado+`manage-portal`; gestor 17 possui MFA normal. Investidores QA 13/18 não têm gestão. No ativo, a leitura confirmou contas 2/13 autorizadas, 020000 instalada e 030000 ausente; o dashboard ativo contém título Gestão de Oportunidades e ação antiga Criar oportunidade. Não há hotfile/cache de configuração/cache de rotas a explicar a ausência. URL configurado ativo: http://portal-investidor.test; **URL/conta da sessão reportada ainda desconhecidos**, sem atribuição especulativa de causa a essa conta.
+
+- `dashboard-active-readonly.json`: configuração/contas elegíveis/instalação/manifesto ativo, sem boot HTTP/escrita de sessão no ativo.
+- `dashboard-opportunities-http-qa.json`: links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtro archived→restore→GET. Oportunidade QA 13, ID estável/quatro eventos, 12 originais e relações/documentos/dossiers preservados; 6 publicadas mantidas; outra conta 403.
+- `dashboard-manager-mfa-http-qa.json`: gestor 17, MFA em duas sessões→dashboard→gestão→recuperação/reload→logout; 0 alterações de registos. `dashboard-navigation-catalogue-qa.json`: menu Painel da gestão→/dashboard, dossiers privados→/investidor, atalhos únicos e ausência de gestão para investidor.
+- `real-estate-draft-http-qa.json`: outra oportunidade QA 14, rascunho imobiliário parcial no draft existente→nova sessão→patch merge→cinco 422 sem mutação→outsider 403; schema normativo SHA 9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
+- `dashboard-real-estate-qa.xml`: casos nomeados Dashboard OpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest, 8 ensaios/201 asserções. Typecheck, build QA e PHPStan dirigidos passaram; contagem não substitui os critérios visuais.
+- `resource-originals-preservation-http-qa.json`: cinco binários anteriores preservados e novo PDF válido recuperado/parseado, 0 novos recursos. Prova ClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
+- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`: fontes/trechos/IDs/versões preservados, 3354 requisitos/linhas e 5830 ocorrências; 3349 abertos apresentados uma vez cada. Estado AUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.
+
+Revisão atual não candidata; nenhuma aceitação integralI 1–I3 por contagem de testes. Cadastro básico de oportunidades não é dossier privado; operaçãoQA 13 não criou dossier/etapa nem alterou as 6 oportunidades publicadas. Rascunho imobiliárioQA 14 não é decisão externa nem contrato completo.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Lote independente I0–I3 — 10/10/2026
+
+QA exclusiva: http://127.0.0.1:18097; alvo confirmado `desk_restore_20261009_174726_test:55441`. Testes de feature usam outra QA, `investmoz_test:55441`, com guarda antes de qualquer escrita. Sem alterações, instalação, importação ou publicação na base ativa. Cinco fases/19 etapas preservadas;5 dossiers/95 etapas na QA web, sem criação de jornadas educativas.
+
+| Requisito | Entrega e prova | Critérios ainda abertos |
+| --- | --- | --- |
+| AUD-GEO-01/02/03; C38 | Correspondências explícitas Maputo Província, Maputo Cidade e Matola; descendentes por nome exato+pai. Ação autenticada/MFA no servidor 18097 insere 32 limites internos:2 províncias+8 distritos+22 postos. 361 originais e 1990 geo_locations preservados. 32/32 novos recuperados via endpoint consumidor; público: 0/32. 393/393 contextos por serviço;1920/1920 referências territoriais por API. ProvinceSelect liga o nome guardado ao preview sem reescrever valores. |31 distritos/157 postos por nome; localidades sem polígonos neste exemplar; integração renderizada por consumidor e ato de divulgação separados. |
+| AUD-COUNTRY-01–04/06–07, STATS-01 | Provas renovadas por método/formulário: perfil/empresa/manifestação/público/quatro apoios/carteira/interesse público em negócio/wizard/fundiário/três Balcões/simulador/CRM. Gravação→GET→filtro→agregado quando aplicável; residência/constituição/fiscal/fundos distintos da origem declarada; unknown preservado. |Seleção, recibos, variações condicionais, filtros/tabela e nova sessão na interface. Não contar testes documentais selecionados pela palavra original como requisitos de países. |
+| AUD-LAND-01, PART-01, LIB-01/02, SCAN-01; C39/C40 |404 dos originais cifrados corrigido em fundiário e sala de parceria por VerifiedDocumentBinary comum; novos uploads registam tamanho/autor. PDF/PNG/JPEG com ClamD real, hash, quarentena/perfis/partilha/revogação/adulteração/recuperação. Lote documental QA privado, idempotente, sem substituir identidade conflituosa; actor sem permissão/ambiente ativo recusados. |Renderização PDF/impressão, ações visuais e restantes consumidores/tipos; lote ativo autenticado. Serviço ClamD real demonstrado separado de arranque/manutenção permanente/GD ativo. |
+| AUD-OP-02/SCAN-01; C41/C42 |PDFs sintéticos apenas com cabeçalho não provavam legibilidade: novos testes usam PDF válido de uma página, parseado independentemente. No servidor 18097, novo PDF anexado à oportunidadeQA12→scan real→download→nova sessão→recuperação; outra conta 403. Cinco binários anteriores preservados por SHA; PNG/3WebP recuperados, sem novo scan das derivadas. Credenciais fixas do script removidas; passwords/remember tokens de dois atoresQA auxiliares rodados; MFA/conta 18 preservados. |PDF renderizado e interface documental pendentes. O placeholder anterior permanece conservado como evidência e não certifica abertura de PDF. |
+| AUD-OP-03/04 |Schema normativo §26 preparado e rastreável:110 definições,9 contratos Create/Patch/Response, sem renumerar IDs. |Workflow e validação/gates especializados continuam não implementados; nenhum fecho funcional atribuído ao artefacto. |
+| C37, AUD-UI-01, I1–I3 |Evidências anteriores conservadas, nenhum novo ensaio de login investidor neste lote. |Login/reload/logout/nova sessão e A/B completos na interface continuam pendentes. |
+
+| Nível INE 2019 | Esperado no exemplar | Resolvido QA | Pendente |
+| --- | ---: | ---: | ---: |
+| Província |11|11|0|
+| Distrito |159|128|31|
+| Posto |411|254|157|
+| Total |581|393|188|
+
+Os denominadores da edição 2019 não são os 1920 territórios do cadastro existente. [188 lacunas por nome](correspondencias-cartograficas.md), incluindo Cidade De Maputo agregado e Mandie duplicado no próprio workbook; nenhuma equivalência por código/fuzzy, nem fusão de cadastros. Aceitação das fontes oficiais preservada.
+
+**Mesma matriz, sem requisitos amplos recém-fechados:**3354 requisitos/3354 linhas canónicas;5830 ocorrências de origem. IDs, fontes, trechos, diferenças de versão, critérios e estados conservados.
+
+| Estado | Requisitos/linhas | Ocorrências |
+| --- | ---: | ---: |
+| parcial | 3198 | 5380 |
+| não implementado | 146 | 440 |
+| dependente de decisão concreta | 4 | 4 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 5 | 5 |
+
+Evidências privadas: `geometry-crosswalk-http-qa.json` (aplicação posterior22, além das 2+8 anteriores registadas na auditoria), `geometry-crosswalk-preservation-qa.json` (total 32 novas), `geometry-crosswalk-consumers-http-qa.json` (HTTP 32 novas/0 públicas), `geometry-consumers-path-qa.json` (serviço393), `territory-catalogue-coverage.json` (catálogo1920). Não confundir aplicação parcial inicial interrompida por Mandie com duplicação: as 10 já aplicadas foram reutilizadas na continuação; ambiguidade nominal fica pendente e não bloqueia outras correspondências únicas.
+
+Testes dirigidos: `geometry-crosswalk-qa.xml` (casos de vínculo/pai/exemplar/conflito/replay/reversão), `document-independent-qa.xml` (dois percursos PDF/PNG/JPEG/perfis), `document-batch-independent-qa.xml` (um caso ClamD real; dois de fixture), `countries-independent-qa.xml` e `countries-forms-independent-qa.xml` (métodos identificados na [cobertura](cobertura-percursos-i0-i3.md)). TypeScript/build/PHPStan dos componentes alterados passaram. A guarda de concorrência recusou um arranque paralelo de testes; ficou em `countries-forms-independent-lock-refusal-qa.xml`; o ensaio sequencial posterior passou. Isto é tooling protegido, não falha de formulário.
+
+Complemento documental: `document-types-fixture-qa.json`, `resource-originals-preservation-http-qa.json`, `resource-http-actors-rotation-qa.json` e nova versão de `resources-real-http-qa.json`; versão anterior arquivada antes da atualização. Credenciais novas somente no ficheiro privado local; nenhum cookie/OTP/body exportado. Não alterar os originais anteriores para tornar o ensaio verde.
+
+Código preparado e QA API/persistência demonstradas neste âmbito; interface não demonstrada. `candidate_revision_fixed=false`, `integrated_ui_ab_passed=false`, `activation_ready=false`. [Backlog atual](backlog.md) e [ordem de ativação/reversão](plano-ativacao.md). Não há candidata final nem novo backup final de ativação emitido.
+
+**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores. 361 e2/39/179 são a baseline 09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.
+
+
## C37 — MFA QA recuperado; cenário A visual por retomar
**C37/P0 — falha bloqueante do cenário A reportada pelo utilizador, corrigida por código/HTTP/persistência QA; retoma visual ainda pendente.** URL: http://127.0.0.1:18097/investimentos. Alvo real confirmado antes de qualquer escrita: `desk_restore_20261009_174726_test:55441`.
diff --git a/docs/investmoz/v2/auditoria-portal/inventario-fontes.csv b/docs/investmoz/v2/auditoria-portal/inventario-fontes.csv
index 2d67405b..bd895ac8 100644
--- a/docs/investmoz/v2/auditoria-portal/inventario-fontes.csv
+++ b/docs/investmoz/v2/auditoria-portal/inventario-fontes.csv
@@ -1,587 +1,593 @@
-"Exemplar/caminho","Bytes","SHA256","Tipo","Nota de leitura","Disponibilidade","Uso em cálculo","Situação jurídica/documental","Edição/versão identificada"
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp","451286","0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx","6005783","ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image1.png","1208097","1495ef144a048018723db1c0e11217fa14b4d7b14d8e65e32a3adeea23d08c4c","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image2.png","1302649","fe235f3c808f5c0804023dd4c1a079310bb2806806933fa95519f923af759f34","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image3.png","1155707","d791e296e6436c52e52d3d29954a83faffde2f8a1228ac48a0aee9753aafdb72","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image4.png","1539","f2f900bc7dd199be5f3e037424a5daa0e2865b46fab8f5a24f9359df1594e144","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image5.png","1180837","9e28b4fb57f6df624545f1ba63b778a7d5c92ea88dc5d4c6cddd97d1c9fe059e","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image6.png","1134030","dfa0c37b886b5fd9df356f4b2f3c24a1199093abf8fc60dc2ed335e4bb68dce0","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\FICHA DE OPORTUNIDADE DE INVESTIMENTO.docx","96615","d52bc22b8646f64e5ddb70811793f7d8b46197f4665b6577c8b25b1910ab4768","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Necrologia.docx","53217","21612c9490cf1382e5c1d4499a10d785f8b9add70322132f32af63449c0f1010","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Roteiro de prestação de serviços.docx","16405","3710e58dad14e8bd6c6aa1eebcf1d21fadc391959681a9f0fa6a139355716fea","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~$vos modulos.docx","162","076a465696c65ff00fce492da12479cbe10d1731e38ca12d3ebd4211111e0fdd","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Guia para Identificação de Áreas e Corredores de Investimento.docx","104659","6e8fec17b7f6efa2cbaec46abb9c67b37693d350a5e3d540aa362a769ccd5ea0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Guia para Identificação de Áreas e Corredores de Investimento.docx#word/media/image1.png","49813","c8b4bb1417aad29a159c3e5e9576e726a1d50aece731d8fc381238ff3a0f2b65","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~$oposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx","162","6ace089e8d5e3f734ec77f9e93cad87834ae58892871fa0b6f98586e5576bdd7","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Agenda2025.ptg_.pdf","1064241","6b7b13eead5191bda3f0318941713dea16fc6d57bbc61ad6f1f3c9efa67672b7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\MARP.pdf","490336","4884bd925ddac14c1c490b822d4ebc391e121df6bb64cef4508ae713fdc59625","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\PENSAR-MOCAMBIQUE-2025.pdf","21361335","d70450b6dc90370bd4a6730d2dbabc3ae1b33a6dd775de1b3b983744d497fae5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\2026-RNV-Report-Mozambique-1-1.pdf","5686850","305387a6def4f1646644a0a50dfd27bba4094d0639915b5371e403253230e8dc","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\ENDE-2025-2044-vfinal.pdf","3667603","520dd8ec3924321f69d3d58466aec833cf321b007b31fc8dc7fd70bd49b0d42c","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\RELATORIO-AGENDA-2026_July_02-final.pdf","1136956","9ffd1074a438d59c6978c8da36fa777abbb351a3c2039dac0fef118b3749ad87","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\CMuendane_ConfInt2026-MPD.pdf","636021","708c5a38cf04438ce371f1a39ad2f5a13e0b78f3e45b86693f5a963959dac2ac","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\JFerrao_ConfInt2026-MPD.pdf","781278","7debcaad44e8a2df8cba70256b519f4cbebb89454fbf3e5fe7ac0550e74297ae","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\PLatilal_ConfInt2026-MPD.pdf","326252","8690da2f9ac9d00e3c826ca7119368c17e959b9ebb945e74427085c2be02d714","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\PORTUGUESE-Mozambique-Special-report-2026-vf.pdf","6768008","c1452219bcb608fb4b0fd51f60eeb676d09b6ba867f43c3178466b01c0783c44","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Capital social recomendável.docx","17137","3b86ae01cf839502792fb130eafdfca2a0a0b6cea10d7f445f972196de766ee6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Para a actividade de prestação de serviços de consultoria financeira.docx","53137","bcae28d5437bca81d6922678051424740e56db2fdb931fc7653966b6f04e2361","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Consultoria e aconselhamento financeiro.docx","24096","5a1aa63b95f5fd45e874b20b7668ef18e715a0b8efe1fa86943784844d88442b","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Minuta ao BM.docx","18441","96a2f0c56836193409e960362c8de72a28f266e73fac594a37aeb9c81f2baa67","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\REQUERIMENTO.docx","22496","e79179abbc20030dcbc6ee91bfdd74a7265419b2b5a473521b3ed2ae60674904","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan0001.pdf","140871","3c1143fd565d92403e0c175adfbea293afc3f187fd6a201ba26e1d45a998d2ca","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan0002.pdf","88860","b6a0ccac07eef71294089dde653f6ed3e600196b75836d69c0e99687e199d6cc","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan.pdf","174964","732ff341bbd4c0c05e8accdb6919fa6151d18e50e0c3ed0cd618a4fd69b9018f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\exploracao\scan0003.pdf","144995","f1f5778426d16fad122f1df32f40df1b2cd66f5c56ca41a9ea56499f10ed8d60","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\exploracao\scan0004.pdf","150054","54ee525982c78450611a3c4b93f77ecc00493decdba4cf982bbc45e52de1cf01","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Formulario\scan0006.pdf","243123","a45ca527e0581b95939f0a35bf107bf78f24e183513e5ce4ad81c0fe6fec3e53","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Formulario\scan0005.pdf","286614","d994a036effb269a1bf808164518fc251458379cc15f1a4d5730e8bd746a9a37","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Uma empresa cuja atividade seja prestação de serviços de consultoria financeira.docx","29727","cf47dfd9686b1d9d8b13288d9b08f720d383cf69abe98f3dacc859c671b3e839","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatório de avaliação e melhoria dos sites da Tempo.docx","38778","ab8a7dc7fbc84bb6f3986b02f9d7cae687708fd501803bf468bc614e1d6ea48d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Checklist para consultoria financeira.docx","34071","55d26f16a8da9cee38a5af23c4c4a3f8093d22da096a6d395e3303c218d893cc","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Revisão de Arquitectura, Dados, Segurança, QA e Produto.docx","20577","b30968b1ea37c14bdd6b4d069aaca66dd82cb8e38d2c3575923b23a23b5430a9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Excelente iniciativa.docx","68066","4583386335ddabd88ad9c2910aa30990a4794d90002ea36cca587255d4a9282f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal do investidor nova versao.docx","799591","3f5040c038fb57702e6cdfad31318730013f9831dd1def99a63df2a084354333","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal do investidor nova versao.docx#word/media/image1.png","708019","753b54d3bef8f345127bcfb3c5272a96c89a03b65436bfaff86cfd22b887a7b5","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1d.pdf","245701","80ff061f26ece6906cc61bb6f0e738d437a6e8524511b80c0f597a919041b0d7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1e.pdf","215107","cd61f18a374a4d1124bc4a422396f77067f0b92ae18ac35ed3ff1bddcc6ae321","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1 6.pdf","239566","d7f27e01dc9b7369ed60de804ddb7b8c1b33011c00214f58d92742a2648937cb","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1f.pdf","253712","cb6dd9134ab2c1708bc7f746a5c8e4969ce7c2bf750b326cfb06449a21361914","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1 3.pdf","253712","7d4337a3eb78f71aeec818d9d5e0fc3c35aba5b16cbdd35fff2d731918eaab43","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1b.pdf","249702","c8b5505759bfb1beb28110cf0506903776e0da032e5f2cc5f69b32b23586488a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1c.pdf","259985","f43ddc80836b8739c406b4e869ebe103732a7f1e37d6a44bc7657619f0959b45","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1a.pdf","273681","9b6abd4b188d8301e6d0edda8c9b576c4d6f058bafbe7be6e234e9cebda95565","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1.pdf","351770","c198b8b7cb2e1eee5227be0aada5193cc73435848ca1aa0a354752db73526722","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\aereas de investimento.xlsx","36868","92921856c0b89e22187ac4b370438dac6023c55dcf335b58f6e37d9dfd4086c3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.docx","799605","9dee08d0ebbbb262651a01ffc7e0ade97323664bda59fe8ce0b07ead82736ce1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.docx#word/media/image1.png","708019","753b54d3bef8f345127bcfb3c5272a96c89a03b65436bfaff86cfd22b887a7b5","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\DADOS cartográficos.docx","18479","42564bb1d940ca4746317a1c7eb0f81212b8ce5a1fe2a98f993bcdd5835c7130","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor.pdf","239566","55124d6417821f0b0fd2ecf8dac40bc098fe9638cf3a281b338ed3643e6b85e5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.pdf","530948","6fa7029ac4beba6979ed08b33f5264ad4f05b73139d79692b03feae41cd21105","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Principaispetos da Lei de Investimento Privado.docx","47642","1a11706f2a63153791e85394f361ba2c7e67c671f738570e3e962824bce2a1a6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Principaispetos da Lei de Investimento Privado.docx#word/media/image1.png","358","b09d2b50f5bc910bea7dae0125f4d85712072673f411faddbe983261542a7544","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Progresso do upgrade — 25 de Setembro de 2026.docx","19826","2e0441552afcabf084b6f9044457b3217823105cac748d9062b35f274a9f02ef","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\requisitos portal chatgpt.docx","70761","b83360bc1805480d176f346724e0a28f77b3affcba575e2edd2e08b641352642","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\upgrade do portal de investimentos.docx","1332169","471012abb0f56377956f4ab822fe3186e2561bee0471508a5d807091f2e0154f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\upgrade do portal de investimentos.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Unificação dos Portais.docx","41650","5b8f4e35c77f8376eb55d80e0b05826c2a754d76e285e2a697a98e87f52c482d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\sites da tempo\Avaliação geral da página www.docx","48183","1a5e2ca2554b59c5ad484c6f2ddc5dd96a905d6a91fa37ebae1fcd92a7793828","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\conteudo local.docx","28720","5f8b2bff0ca00f2cd85b6fceb1972dc22fdb4a2624e51dff1b26d958f642494d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Progresso do mercado de negócios.docx","18811","e6fb8b747ae21bdb741b620e48c4c3744a01dfc19bdb3e43bbc7ce7ed458ee89","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor (Informação Pública) movel.pdf","367810","f321f8490cd25792ca034b32b5c9ee197c59c703bda0afc04cbe8cf65c57bf58","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Vamos criar uma versão do portal do investidor onde.docx","22443","1343b30014a2fa4bcf428d65b02d3985ba56c7ed477d7380348f8920b1cad6b5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2h.pdf","258241","e712b549b7dce6fb9b3f23148e4bbbe7400900740139d0b14c871d434a06b6b5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2i.pdf","220076","6f3bd3664394b85cc4d5d4bbd9bb17a78ec462af65d9a9e7ab6e945b2cf3bd4d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2k.pdf","214882","a5672e4078ff74b26307dd35488e16427c50bbadac99be31ad360377c9d55eff","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2j.pdf","209176","1554440ab74ab98810c550b25370291e4d0c3c8eabf43a940acb2382a9da51ed","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2m.pdf","235400","3307b93b078ffb270482bb8eb2365f71acd023d53204dc8f3dfaeff93087dff1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2l.pdf","219233","257fc4e938899a47da0090a96d2f5b401afe3e5ff981acc5d9f6d8ed5c4dbb7b","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2a.pdf","418445","f10d866eac013a917eee7890117e30c687bbf402202ffa9a12732c2b92514b92","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2b.pdf","270399","699f05745e6413132e4f0092cc903f702be31651bdf6436fa71d16a75e09b03a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2c.pdf","291689","590c366991383f36ba11c99da810aa07f84d50d257d3402332fb0fe1ab72b5f0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2g.pdf","247322","aa524c56eb1940c14575d8352497ed256a0aed24732eea2d3358a264d12cd2b8","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2f.pdf","245144","53cb235137563ddb1cfbb0d7366f61d4c4844521f4d325eb40ebe8f68d24d3ae","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2d.pdf","263586","a995e7c92e6a7bf19f04e7892e37d1771df2b810876f976b7d4c1cf5c56884a5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2e.pdf","222937","2c137bde9bf606887e395ead7c26fdf639af94a12865d556eb1a3767a2602375","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\projectos.docx","62841","f37afdbfd773befc742146f053de765a1682ea93123aa614947c1180f64d2013","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\integrar o SuiteCRM .docx","24325","79b04d446619f6dc9a3bd5e533ee4778bda196b9dff6bc228b365ba0e6c87279","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Matriz detalhada de oportunidades por sector.docx","30331","73d7f7792631d144d69616061354b88fcbbedce825d0af533d5317ed34c8ccd6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Portal de investimentos v4.docx","1662261","a0438b98c56ce930453f3eb519a952b3274c01fc421b2a2b4c5a994e988a84bb","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Portal de investimentos v4.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~$mulador fiscal.docx","162","e0180ad0d9fc11f260e4f3c5f49fc648f55aa18e9ef100925cc054414bfdefaf","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v6 programacao.docx","1658773","e1169a7743b13ff6c950d3ffd4672a2afea32e81da84885e11154b7d8de9241e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v6 programacao.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos -casos .docx","48412","b44ec86d313eee6790be68a829f43e00c21e191c16cb89b4f8c37dbddc26d0ba","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\correcções a introduzir no portal.docx","21538","bfb24adfdc43afac8492b30b6bb2b7c57d5a3d57c7cd36008d9fdd5a80cd7dc5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\cartografia_moz.xlsx","841177","2c5728c46973866371139cb080b1b1837bb980a43ae91693f0b58f2263a6c455","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\simulador fiscal.docx","70093","55997917b3bd85727cffac880b6c46fc85a78fef6a005798b9a110a0bca60fd0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v1.docx","1338438","f70ce3075523c6278e00dce15b9c7acf2b690679e16959ae5f7d007e754cfc6e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v1.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v2.docx","1417663","51b8f0ad3296d1064a5c12b450874fc72640869f10a164319cd7f3153dd3a086","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v2.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~$grade do portal de investimentos v4 programacao.docx","162","096add1ae344654e4bcfaf80cf0578da35022211d0937a11d4288b809cec2f4e","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v5 programacao.docx","1627296","edece80c0519537244f8a8b86456af0aa92de1c526f791bb0ee9b85af7a7e8b2","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v5 programacao.docx#word/media/image1.png","1137172","06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\simulador fiscal v1.docx","142685","f038d338fa0247ddd70f9dd34e72b080f9b7c93acfc02aec0d433bca1ee606d2","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~WRL0388.tmp","81042","2bdddd284d9c728eb4c1d93a90dda11eda1d74640091b54ed14e0577c0d5ff4a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\IA propostas.docx","38021","2ca6ea33195ae3715ec6823980b720ea011ade6716a9885ee32d69f808f0d529","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\codigo .docx","53404","d3b5424c916ca3a727992cfeb33cb9f03c7ad54d2bd6a4156c11f94bf048223c","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor 1.docx","388939","efd550fd2a9d2a21785d7b3c140d4608f1ba27c52f156e2709e9fbf388a1a569","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor v2.docx","403675","9f5719c8b0cf78855f727d980b77a8f9409fc7f93e303e25d355d009a07d5734","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor v3.docx","132293","626cae3d584658842ca36b658e7b5b3cc98d87036747e65b29274f0209734e5a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\instalaçao investemoz.docx","15796","c74196f927250a35778ab5896e17567aa9689038b99850ab09659b9b7f2aa89e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx","5456742","bcbf8ec976100cc5e978aef54050c3e3e9d959b0d361fa80a788528a8e5049a6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image7.jpeg","545244","d98834afbd035360b025571e38d583b0ed5458afe7f88f0f646badeecbbc40f1","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image1.png","2824071","bc81f42453ded18fb3836b665779ac9100d0f3c70d5b6a2505cc5240fad4b2d7","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image2.jpeg","468173","c948779500880f5b541a49d96a64c7995e8a41fe5fed9d4514c609b3cceb0ffa","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image3.png","91096","e4e3b71dd820cc3733ca0e7bed74be22418122affe1a1471d62a10a6ecb5ee17","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image4.svg","6746","d5cd72d2a0f875881c47f2b48945ea54da1a284256da3c1e17d788946eabc3c6","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image5.jpeg","678237","3358f74fd99dcd54449349a37e3bbc8010acc4904b6cfc516a9e7228b54590c0","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image6.jpeg","538480","efc4716c0764b2adecc020d7c650e6f7725f8ddd2c670f3f471b6c9f50063a84","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx","156864","b1173162e6cd0c4b5bc41dc224685cf0e50f1de36cd70f7bb1bc7a7dcc873f4f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx#word/media/image1.png","44266","4becafb4b86fbdcf74bb8f79272e3ba79be99435ca9e853c6a398cfb836b2d3c","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx#word/media/image2.png","66716","ccc2bca23bf03dc49354f08dcf9ee341568ef08e3b106682fd7ef1ded5a77b04","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor (Informação Pública).pdf","417543","c5d574c59fc0587ba8889125f775c88b690834d91125518e959b273a1cd4ce66","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Auditoria de cobertura dos requisitos — 25092026.docx","27257","071345e1cbca77810b96beece4d44e12c57242cf6cf99a6349ddce45affb9207","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\sectores.xlsx","10689","8e263ad5a450903e856ca0a2ca10770951638cf1b90dee59a31bf0c5e567357f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx","2392539","0c91bfa7a2ca1af99f8957597d6225c4e56567cea723ca8004e6661c4bd79513","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx#word/media/image1.png","1036841","c189c22ba98ec837d9b8e934a904666b316371baa62132b59d6e49ac72a5f334","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx#word/media/image2.png","1233132","ac02380189d8ecc388625eeb3737043c722fb35ae4128d3a7fb8508a39c3f466","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\recomendaçoes do CRM.docx","21697","427cd1df6fccd888e24e8c2dbfa81e2db86a4132fc24d7a618e09ed0f399e220","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Benchmark_InvesteMoz_revisto.docx","54060","7fffb2a6ba01ce605504896f65bb078e5f9f906fa399942ca9f4779889809617","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Vendas\vendas da Tempo.docx","62880","52c613bc4301d388d6cdedf90af5074ce2ef0e7d06a7166f25fb352cddd0e55a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt ZEE ZFI catalogo de invest.docx","81500","dbd59fd85026e8d2cd89a4666e2385191fc1cba376bb45b7425064c6deac8395","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt ZEE ZFI catalogo de invest.docx","162","6d45cebdd4fb18b8ed43e6b54454804425810ad3b21312165aae25628795aa61","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Fases de implementação e respectivos prompts.docx","20742","bf0a33961c3b0f68f057584fdd6c2b62266f617ad8a3cdff297e7294138b025d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt tabelas ZFI ZEE.docx","34492","22010ee3d77d91474912890640fb74c42f81bf20fe7ef416ee54a9018142e4cd","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Método para executar as recomendações do relatório e corrigir as lacunas.docx","29103","d57343711b38352901526e18945a6102f8aeabf377ebdc4eb135e89b5dac1783","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Prompt a serem aplicados .docx","17943","757551ae205520aa61c688a922a88e2004b7b70bc44db31d08d1d11b5ff7a24e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Iniciar uma revisão funcional transversal do portal.docx","18499","99a85c7b7fbab720f958eadc5cc49c61a07c49eb1e45cd79c4b8492193710230","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Detalhar a arquitetura de integração do CRM com a IA.docx","19823","15415735923b3753e499d8789310dfcc6fa0222191f826cba002ec2d239e1a01","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Definir os campos obrigatórios das imagens.docx","20689","5c126b3551be81c27a8b8297cf20aea5f62868d0177e5312b37e6d04b0adbb28","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Optimização do Catálogo de Investimentos do Portal InvestMoz.docx","19378","46f95f4ed8271fdd7aaa088bf861eb4617f16051f569980e76bccf5cbbfb3c6c","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\perguntas para o empreendedor ou investidor.docx","23887","27d06a797640e6cc5e1dae45ffc84822081cecc32565fc9c9a2a5bc9fd273458","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx","423661","d82b35417f3bb4436cc33bd96cc367a3592d88d9ac0e74d413d502ee0a454849","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image1.emf","146356","675a4fd6492451e600d249ef1602349ea1926f2912f30a243e9494da1a03971a","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image2.emf","118956","3130897bd1fb72233d1bec77d3da86fa92af2bc1440b2059b5b7183f6d23a2d8","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image3.emf","30908","c4c51dde4088e49b62e22cab8a8f6c9c9bf7c615c0315c6da1d90b1e89a9a1bb","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image4.emf","874048","cef9c9cbc48336475524dd2a044f80482ed62a7422e03568f61ec4b7a33b3ccf","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image5.emf","255104","1dc259f7113bd5ff47af5cf4efffcdfb8e719973df714f3e31114e5a5380526c","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image6.emf","170372","8f4fe8e4c6cbc331bacf91595533cfb87b0edbdf05ae268a2ed9c7edaead1f21","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image7.emf","136852","2fd409005f2e33ca011be5d9ff7aa460c0c54c5f40a2b9093561b7306ae49a2f","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image8.emf","216420","247da53a98e039cdcc2eece983bd2c4f1c283990fd641fefe3c5ec738997ff76","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image9.emf","99936","fbfebba12507d917e4e57a1f7e29e71a7bafe0cc69ac20c2da6de967ede2087b","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image10.emf","213556","8841a3576a2f4a62dafe0d5aa495d215386372ae1c4c82cfe5b0968841a90edb","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image11.emf","84940","7cbd43169ab16ef7ef00f85a50b8da774660753305870c8dd807d848ab8c1f56","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image12.emf","271360","4c918c38f44d7af0ff07945f1a4f0137b0d56016a47f43a67fdeede8b3cea53f","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Formulário de registo de ZEE e ZFI na InvestMoz.docx","25178","9de3ad1a27c040365d3f688ed178cc0994cfa29014c65ec28589b2e76e4068b4","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Recomendo que o Simulador Fiscal do InvestMoz.docx","148831","faf42f9b69c64291f1ec9be268e912bbe964fad9651e30f3467b6384e4ef5258","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario para publicar uma oportunidade.docx","23372","cb1a117ad5e33e1117c4601ecbb43a7b51c1248df654f0c157b4fa593b55fdb9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\~$rmulario investidor etapa 9.docx","162","5cce0235d6093310a048fea6e95053b544a46485c9408658e679729d282346f4","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Melhorar o simulador da investeMoz para utilização pública e empresarial.docx","25831","f3116bf51b04216f9f524f5d024288c9a2c04ba0c79a284b86a808c6808940a8","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\novos formularios\Especificação do Formulário de Cadastro de Oportunidades de Investimento — InvestMoz.docx","320004","9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Formulário de registo de clusters na InvestMoz.docx","22723","e1a546e7e2d6996b7f92730e6c1421dd6faaef64a45970a30dd5770f91035e4f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Requisito Consolidado do InvestMoz.docx","20847","44295a85c3ffb8568ae4c496167fd5d79381d44b0724f4e11ba6e471cf4e1ab9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario investidor.docx","55430","380df6e0c7236ef208df93b4a1db033db71c04033ee131c7ab98668adf677f17","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Restauro do portal.docx","44491","12a297f80796c6fd753bc385117016a8f86940312fbf380d52ac25bc403e2210","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\oportunidades de negocio reformulaçao.docx","22890","11bded2839398f8de4f10d1f653200979eb29b32735417f2e380d92d6109e3a5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario investidor etapa 9.docx","55432","154f96a543febd6b9be51dd26025048d13e7e0efdf51ce88770d2b561891fc13","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Zonas Económicas Especiais e Zonas Francas Industriais de Moçambique.docx","22246","41093a37ed1265870a3f4e0674ac7218ac4b7bcd7047ef8d927b69750b9f4f50","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Prompt de Validação da Actividade Realizada até ao Momento.docx","26196","827a850ccec7616b6033754869042f9a2ccd63b496b60e253918584ef913a52f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Matriz detalhada de oportunidades por sector.docx","30061","9f52c797dff6f7adf1904efd6e15aaa8f552b7443e57269533c39b428c20e9b0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração de ZEEIntegração de ZEE, ZFI .docx","24398","086b0468934443d48aebe6707843d481faeb323e78b161a2f5af0c2283217773","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\parques industriais e zonas francas.docx","27152","c5a6945239ea9ca5fab18510fe15e33deeffe8fec72d811f5a639c7388fdcab3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementação da CAE na investeMoz.docx","18546","ed71465abc672d84471117f710c5179160815d3a02c1c121bd43c915bdab38eb","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\DUAT.docx","25817","9453ba3bcffab0132a1996aeb26d0048cbbb6a3b52a9d0b6a5f7a44129a553f9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes.docx","444929","b46d377c5e98268110b64851fd9f1705a413bec9ae7a4eeb4c9c0f2d4160801e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes.docx#word/media/image1.jpeg","383819","a23b342fab66e292cdbded2e543dc29c70ea0a2e01cd5c3f0da804a6bb81291a","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\tabelas a implementar educacao.docx","29789","8471f5f41f5113ad779684f6dc0d62099f130ff08a4cfc74265dc25afdf2d693","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes v1.docx","466730","3bddd804585cee55b6d22fb49d551f13da1b4ddaba237bc5d34dcf85eb57814d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes v1.docx#word/media/image1.jpeg","383819","a23b342fab66e292cdbded2e543dc29c70ea0a2e01cd5c3f0da804a6bb81291a","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Base de referência do directório empresarial.docx","18391","7e4f6dd21185ea69560907edd119f318b91ec4f156b693bf945d17954017bec1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\prompt de gestao de educação.docx","52637","94ea9a82cddc6e4e265d630f53a464d69a294e93b237b1ab395c62517bf89040","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Complemento consolidado — Criação de empresas e minutas de contratos sociais.docx","20050","b20c6517784b6d44aa22beb67748d3f3b224f58c60a7dcb378a185669c2c543e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Requisito consolidado — Ciclo de vida da empresa.docx","19453","c027dc23895dc743dee65dbc6ab156177226087c2770f63c16bef56219358d36","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Complemento consolidado compra e venda de empresas.docx","19903","bb216f277efc168910d80f32bafcd7649e53f7c72ce4d1f11cf7f523ac7521c5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt consolidado — Melhoria dos ecrãs do InvestMoz mantendo as tecnologias existentes.docx","26653","ac6c720d00913c38fd1fabc6114b73580efd0045cb9b8ab32126df6eb0eaa8b1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt de Implementação da Cartografia.docx","23758","467f4dffffac685a4c2f9e67c844b3c5b9e8759f6dc593723c73242f4e0f1818","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Perfis provinciais e contexto territorial da investeMoz.docx","18558","4ea5eb0bcb3d77cd2623e4fa47ea39838398e9355e2c94400ed590007f1d53b4","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\prompt obrigatorio.docx","17749","b0845167a4c94cc0852b7dc569bc69ac30b472cfecda8f8416d1f7fd1cf7d672","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\~$OMPT Competências e Oportunidades Educativas.docx","162","8618266de24e02c06c049b850f55b03a965145e664175a6fec70167a73e9b7ac","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Formulário de registo de clusters na InvestMoz.docx","25760","31828090185b73dd8594835dd6f850e312a30b824ec9ce593218d3d0eef30b27","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\PROMPT Competências e Oportunidades Educativas.docx","110812","5da580e3e692a3d9e105c1ad98bfa745acdc5db40dec3491f8baa73f98460198","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx","880118","5159afe652cd598520f22c75aa02a3b1e9a51a78b0a29a1188a66363f720feb3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx#word/media/image1.emf","17864","66b170a85568efaa3286e73ec1cd707ae976f42a5487c7978dba0f910e7228e2","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx#word/embeddings/Microsoft_Excel_Worksheet.xlsx","840317","b4544df3edce037a269055be2215b2045917ed372dcf04948e2ec16f95e4b280","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt — Integrar a lista de países nos formulários do InvestMoz.docx","22105","cf7b024ee6401c710662c6b7c310e30f50791729e9f74bccdbf72bedaeba6ea1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt — Incorporar projectos âncora e investimentos do PII no InvestMoz com rastreabilidade.docx","24323","d63e63a5a03275170c6d3037b6c3c17d986ced9c791fcc2d754ff6e3ad4b7730","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Revisão obrigatória simulador.docx","19879","22b7da3b9135c32f392ae0363f3b659242872f12096e760453dc9cd01f5c1ab7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\oportunidades de negocio reformulaçao.docx","22888","8506a1583541cb8db32df9691d2e994aa3bebf99e2e700631c670c056c03fbf3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração dos parques industriais e ZFI no InvesteMoz.docx","24372","640cedda8dcb21651fb1021baecf00b887276a219c528e8aff04f1397831163b","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração das referências de oportunidades de investimento.docx","18441","6803ef863bc63c7b6e4be5398307a7238f057504def841e7d12863f9a437e3b3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Modelo de Dados Geográficos.docx","48773","408815d07b9ad63a65daef15cc2a29d58f85fbe56af0d167914c1be0389ca0e1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\cartografia_moz.xlsx","2235715","1e36c769c4767420b10f1ff5ee0c2955cdb1b03c98179c5cad549e832ffb1f15","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt CRM.docx","29822","8a039779c58d036bb8bfb974e4374086c9afae31fde3b0d6b6e6a1379ae680f9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\realatorio de auditoria.docx","22314","6e2876d13d8c06db17aff1f2284eb0f298c558a9000fdf3e738e02beecb1635f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\PROMPT Competências e Oportunidades Educativas 1.docx","36189","183bfb8860d2bcb1af1bc9b897deeb98ba789fe9c7ecc08e1ec63e87d0e25663","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt CRM.docx","162","e815230666b07ca9e6120d2f77bbdcb3b334892f2857b6fc8b825b6a8166d856","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\revisão indica que vários prompts já foram parcialmente implementados.docx","21552","4e4fc9949eb8218dbc01c922efb184d906409c41a8290f4d984b089df00d8aa6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\PROMPT Competências e Oportunidades Educativas.docx","55730","a8b37ee54ac5ebe8f22238bfe46b011a3d385a593601088a0514efc93d72cb69","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt inteligencia arteficial.docx","34436","769761caee9e4c9b4ced1a71d877b40f3de7c6721c9d85bf6a53c05197cf2370","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt dos ecras.docx","42439","ef26857a139de66e25ee43d3a49ab5dc3e6d4b1f2c2eeafcb3579b74261538ae","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Pacoe tecnico.docx","30860","4c50196c21e1add220b423fe5fa70fdc00f65332872566ec49b1c8d3c5925ac1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt inteligencia arteficial.docx","162","58af9455e09420443de9805cbf484b94721e299fcb75cb02cd12823fc9cac356","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Restauro do portal.docx","22560","ff6a04b4950f9ec3b079db934a37ee7c7df3811eca46890e77c0e981309dfb63","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt para resolver problemas encontrados 300926.docx","21446","ef75499200824189bd8e2e022403d4d7c8d9a1a0128e28fad7915ebc883b12dc","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt corrigir.docx","21990","dd72b1aa7c43af3dac9d0a447e6b0d2304bbbbaec1f9846f13781c74328d000d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Prompt master para revisão do potal.docx","30640","a9963f4cc591c7df88630595bf09b616d408062011b663b9f95cb73b231a61c7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Cópia de dbrosemin.xlsx","20076","6ff3f15d4dbedf78306ae3cf5f53bf3648553280fc74f3184c4ba4b9d37e08bd","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\benchmark de melhorias investeMoz.docx","134291","065203aacfae766c62cf9c2c272ebacc61ff23bd4ff9e91535939fede87f7617","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\melhorar e transformar o Portal do Investidor atual.docx","862272","d0c06a759693e7b74c6daec14539e247e2bbbd630bcaff59aa01b2f7e9aa977e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~$ojecto ancora.docx","162","9424159b007fe38435e4ab829e2f3aee55d514c822278d0d78e265e4db5de9b6","original","Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\projecto ancora.docx","54305","7da1e0f49fb106724c2e416c34905d76249fd27514d0aa2066cde7963cdc4c3d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Corrigir a ausência de ZEE.docx","19153","453cffa885086eabacdae7138879c096649b437f9b4c62572f5d35744cb231d7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Plano de Optimização do Balcão Virtual.docx","79900","74a8ce293f1ffa153c7a1950413fc94c372686c28f5fca43cb751ea6a5f94f03","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Bolsas de pareceria Bolsa de Parcerias.docx","86714","0c2641ce634b977c99df8729c43f80e5935d26e2a4ed0cc5290d08938bcf0be0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx","11997280","a3df44b77878970ef68303615f85a4e88e600ecd6917e6c82d5b29f01b8dfa98","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image1.png","1626117","f44dc437cd1c9b6a978f30fb9ae8977f81e30e4177e05eefb5c5a54cb8626336","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image2.png","1745395","e42c3bb28a1bc0c455904c27f9ba0fc18792efb145fd63c107c3a5166874a4cb","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image3.png","1913792","53fd77a360a7ecb6ff67c733b92d66cdcdaee8ef078d8025243d2cd475a11ca6","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image4.png","1394028","b5f458bff34c013ffffc73730c2637addc7115b0bc58c326881d330969001eca","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image5.png","1382473","f0dbbc1025013174f5bedc453d1e8d476456e36f307850ff1bd66765fdeda09a","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image6.png","1313377","ab52dae6a50fb216b8daaea09b72df019ce9e93ec5b0fb1a3ba8f7eb670e4b02","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image7.png","1437364","72afd50f29f2d2c6e322927a56ba04843c1ca1fa7b9797c5dd91047eb6777e9f","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image8.png","1122339","fc8529eb2af0d89f83003143e0afd039a7e8948ea00aa615762bc669c9d31097","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Estado ZEE e ZFI nao implementado.docx","24370","a1567e498bafeb0665566b26bd0540cad2e5031f79de5727eefce9806a238c7a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\auditoria v1.docx","19610","a58f4c47cf9306a02193d82cb607f8493e47fd6e9186df7c8e41bcc780c69d67","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Benchmark_InvesteMoz_revisto.docx","54060","7fffb2a6ba01ce605504896f65bb078e5f9f906fa399942ca9f4779889809617","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Não há evidência de que isso esteja relacionado com a compra de tokens.docx","21957","f64d930d8a86c11e141b344e37cf294f16273190c2374689a221457a2e3476b7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\DECLARAÇÃO DE COMPROMISSO DE HONRA.pdf","506695","7c9f5af3100b32781018862c4b9e082515ada087a49fdb096feeb804ad8cb466","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\implementar.docx","26053","77c2c84df6b09616dca6392d0c6b78ddab36ab82d7900cea29cae95aaebd495e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Evolução do simulador investeMoz — diagnóstico e progresso.docx","121493","f329a5aed39964f098384ab2e4380bd5f8479bd04551c315984d0c5e535e7aaf","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\SuiteCRM.docx","26455","3dbef3e4fe8cb604be760ac3f556a63bc2643343723921031a2a56ffd3880144","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Integração dos parques industriais e ZFI no InvesteMoz.docx","24369","a3ab1d84abdd83ca9400d622b0a6c0af65c124f6de043840bc739a630a9a36a1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Conference on inclusive and sustainable development in Mozambique July 8.WP edits. docx.docx","34821","3f80c5affb0e54c53bd04e82cc37846e09be9bd67728483852043d26a02ea6fd","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Conferencia Internacional MPD.webarchive","14929099","f37af58ca54667a1c83499ef33230c14021b9894b2c5842d584c1ad337d6e28f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL0575.tmp","1305935","6c5aea9972fdeacd045793abc774473a6001e90d8ae4f4811a00f671a5105470","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx","6803032","c7f725f5515074807abdfff6963cce472420277fe352f4cbc54d438ff4260c00","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image1.png","1323697","8223170912d288e7741fcb884c46d83690d98b525f570ed139b332614296b6ac","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image2.png","1407311","6ef4609c17aba403a0d67e9fc166ec8e148908a4f22e3bc5a084487647386859","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image3.png","1729491","69107fc52e1a7d2ed39821d8ee0977958e382b6a09cbae5a5095784b57f968d7","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image4.png","1865233","3fcd53fdac090ca59834133089a19fd003150c2fb89adba92a896051bb185855","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx","59538","d3ae0d91ac0bc6d6cc73aabda4916f1c8e2e7450a051126ff39e492e3cca7c2c","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image1.png","980","6b6ad303a6c9b48d0d086a2a9e9d30b2de4aa58da44f59d7d93dd8dd3727ff22","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image2.png","13242","e3e34126023e0f413ae599d188d6fd3c30aaf64933711e4c7ac67b9b3fa4a2ee","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image3.png","414","a46bd049cc2b9375f7dce99347b28cfbff2f484d9987ec9f8d4f7d1d99b0e1f6","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image4.png","12198","dbc05aaad4448c31ca450bc3302493c2be6451b470e897c343dcf2dbe0793b7a","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image5.png","579","59212bab985967a734c29fdc3d9f8db77347e87df004d579651562ba486140d7","anexo embebido","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\006f3ea6-5bf4-4315-b3b6-5dda9c3a6566\Pasted text.txt","6842","dbf5afdca293302bb84389ac33aa576c25859f8fa54e26d0b9687b9c564be005","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\0ad28475-97cc-4263-b611-022f3de5bebc\Pasted text.txt","72880","f167d9156c2572c0253949a6f0ed88aafc28450cce902e8f445e3d979119aa37","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\11c236f7-e954-499a-b290-3d6dce07543a\Pasted text.txt","5158","a8241744db40871b36d0a2b39796b7168fadcf243e02a352fa794176da389c95","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\13ef8ec2-be07-4b10-93a1-9fe134b928fa\Pasted text.txt","14654","8185bed1e45611af8861c8f00568a7da6901896e2650355c41642805485ffae1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\1b36f6f0-93cf-49aa-9479-986a57bd18f4\Pasted text.txt","37098","470913bea520a8ee267f8df27c0849e12e0632d0ede2d4556ed463c994b82161","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\1dc38f3d-1455-4b18-8358-899a66386a7f\Pasted text.txt","36260","05ef8ec7da01b185ff0872e917e9fa9c5c1e7407c3d547788f9ad53930dd5990","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\22ddc8a3-c393-40ff-9960-dcf7bd9e34f6\Pasted text.txt","8230","5464cdaab509637a44adc08fe621fde45a0bc16c8fc3aa9483fb1b9f0f9e0e85","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\2368cafa-157f-4177-ac75-255563247749\Pasted text.txt","16046","300ede994ba6cbacdf7ffebb4cbd75777eccb3f359842491404357e8a549b235","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\23b033e6-9ee3-4a6c-a41b-688fe7f09795\Pasted text.txt","44742","5dbf82c2d8ba2c9056b838c4565cb0db9de28da4173075bfdc12b233b3c43fe9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\27922f5b-f041-47db-bbf1-6bc50f3a83dc\Pasted text.txt","37098","470913bea520a8ee267f8df27c0849e12e0632d0ede2d4556ed463c994b82161","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\2daec0e8-1c8a-4606-bb4a-b7fccd0ea7bf\Pasted text.txt","0","e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\2fabbcdf-a098-4a0c-907f-b5cc428c4608\Pasted text.txt","12095","991d4b34e6dadd23f4c66a61de509fbac1abe83d8cbb316dd24ba400c6f13451","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\4b4f7002-adf3-4004-abb0-f389778dc08b\Pasted text.txt","5601","02f44bafea4ba47adc8b24284d4b189ab9f1db3f6c1d1d63fc06178c400f9ee0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\50aa6a01-de6b-4fff-9625-46dbbebd033c\Pasted text.txt","13287","129df97b64e3747d626b89e25f70bba14ad50ccdb47f08eeededd41d0509ebe0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\5d9b9f23-04ef-4e14-89d5-bbe6abb4a06b\Pasted text.txt","24256","b3e17bb11d6ebafa121b623c8ff8949812b35ef0ca5926a33c22f3e2093a01d9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\5dbe0293-16ad-4975-8956-ea48778d6510\Pasted text.txt","23804","6e51cfcd4ee1329c51736e0fb1a47668a8e9550de94ead8ffc222ba22498179b","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\602a2b85-7e0d-49a3-b048-de31d42fafc9\Pasted text.txt","11118","07bc673aa256f0ccc73138f70121077e948650683b2dd24f2ead3dd75c76831b","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\62a3324a-541d-414e-8fa8-8cc25c41ded3\Pasted text.txt","8048","7ee3460c0fc278057ffb283ab33d556f58ed8d9834f420c76103f69a0e18fbe3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\65a3763e-afd7-4ba0-b650-1f4c37f3cfbb\Pasted text.txt","11460","dff87ad6bc8d49d487641e0dd577314bf78f75c3d0220a8802461c5da0c48c7f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\7235d6fa-a6a3-453f-a97c-b6741c083d10\Pasted text.txt","16673","2626df4ca70d52cb5f90247af7b6eebbb251fc64b4915ee0ed1fbbb693cb3586","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\77627963-3e1c-4d41-add5-18eedbf62b01\Pasted text.txt","16486","62719366d33c647930cc4bc92a07d8e933c4f0e0dc06d91e2464da86ca4b6f8a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\777f05aa-700e-4dd6-8dfe-e277214fb713\Pasted text.txt","21531","4a12de1c0822ef8583ca5bc7f3d4ffa8dbba1c44fbfbf4e0aadc345efa696f65","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\7cb98fa0-99e1-4dcc-a3f1-30cfa71ea9ce\Pasted text.txt","13591","09933d0e63883e691a573ef23b7c13fa8fcf66556fe38618e222275f5e327c54","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\7f29e161-75bb-4e3d-b49b-cc885c8a386b\Pasted text.txt","5586","cb34088522c04f92f121981407e3376a2c2e3f489d09272cb1dc2828f8c26603","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\8528a9d2-b934-4bb3-a132-a18b7e13414d\Pasted text.txt","30136","6c2ae3e9b43133940dd90fa2be0d24c07eed06ace5799cea3efc25574c0a0e8e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\8865429e-0156-4167-b465-3595b0fda05f\Pasted text.txt","5262310","b2b4878730a3285d9fcacff5236a15671802c172ff28c10704459aa2cfdfb9eb","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\890e42e3-ce0c-4cd0-903d-d97785be9ce5\Pasted text.txt","68522","d60559844425f03f4a722dff3974be91e8e4e279179bd58663ae164fcc9a68cc","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\8a8b785e-862f-41bb-8d03-06fc6f1b853e\Pasted text.txt","39222","0755f56ae929fd37451d7dd589bed8e1f35c6655f2d674ec1be788b2582cf31d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\8b304349-5505-4827-9c70-f35cd2514513\Pasted text.txt","29220","1f0a4cdeefb86d36719282d409205f49a0b6d9770ee1beb32ca82284135a0993","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\95cf3a5e-fdbf-4005-a877-57d4ac1f93c5\Pasted text.txt","11261","a2434658ad9e75e59f897cb57c4c2934b8a28f879e32584f3d00064900c6a5ee","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\9e57f88e-82d7-45a9-b1b3-4ae8cec7f713\Pasted text.txt","11805","f15768c79a22c039b9137b937da003dd61912cd9e8bb9fd7a40c795dd0af067e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\a1795b4c-c360-4e31-8eef-2daeb930721c\Pasted text.txt","23694","24f36a01c9b6d0894155cbf09c17f128904626935461897bf59ce2b811d08d9d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\a2b1c919-0d1e-443b-bb5e-8917c877899d\Pasted text.txt","54479","06996499b4b5a6b84aba61d43bcebbe9bc7d710700bf279172dd92f1016c8bc6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\a57fcca7-d9b3-45e9-96ab-575b1c5a3536\Pasted text.txt","30350","8e6deaa7f0d738299b1ae3b8bf89b633641e0cc0cb5e7211461601c0c2b6d635","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\a89743e5-3439-4543-9382-2df32e6ceaa9\Pasted text.txt","6636","574657f7fc612bf7760a31f200978b289a911df39964b8c60e3b357845d8bd4d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\aa68e897-14b6-4504-ad05-93c2e3f0b4fc\Pasted text.txt","9536","b207d14e53cf13e621a01d0e2bf4bb82bdb65ad0ba07c457b42923299d0336a9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\acb359eb-1a65-486b-8680-c6abeacccef3\Pasted text.txt","14837","99e36a08038f2540114ad87c32423ce9f0aa6c7c7ac866372273b4fd33df3765","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\b1cdf53f-6026-4724-ba91-fb21b176eddb\Pasted text.txt","7348","e115415527ba9a245fd8d44f4b815054f2f22c72152b5d4ba538488a06d14e85","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\b86ad3e6-37f4-4f04-9bbf-6dc33f69250e\Pasted text.txt","6991","a2ad18c729f00e37db23c1b26615dcee50960e0eed7346d6cc013e6a57c2c24d","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\b93f36c6-ac2c-45f4-995d-577c09b3862e\Pasted text.txt","10274","9f6dd1d9c0ca8628443edc69a6151ba49f96a8e044ac8aface249c4957dafb86","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\bf1d310a-d3a8-48fc-953f-0648622a6c85\Pasted text.txt","81460","fd7878021ae5d18c9d4a9a79073552c36876d59726b8fb2612752f2594080ca0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\bfb8dbf2-ecff-45be-8612-c1868ebe8343\Pasted text.txt","6665","cc874c1e0d7ab1d7779df1664c524ae5f876ef7af99b7fec2358c4be7d0e53c6","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\c1ac842e-1b98-4f18-82bf-5155dbddf288\Pasted text.txt","11603","bd55cac92926fd804e358921924740eb9c7e649af7a845fe85d2c3686ae2ef09","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\c6245408-7052-4478-8804-377b282e8203\Pasted text.txt","30976","600240dd64b59b82bdb92e471b475f9efc96eab67f9cd532a432e1e7a324f0c9","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\ce3b9157-6463-4c3f-af50-6d53cba78a23\Pasted text.txt","30586","6381a59fbe8bd8ee5a76d8755ceb320ef2d14fc1e628b8e1cbef2c5eb83e30c8","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\ce71e769-044b-4eaa-9f8a-793e52cd644d\Pasted text.txt","6128","0a64d4fe9dc2d80211568d74cc49335472d7a2be01a199223bf4b1a0fb58e983","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\cfe4012e-cb54-4a42-8fcf-9567bea45d7d\Pasted text.txt","34983","8ab2b0df6b41a483d72aa852984c627a1c41dea3f05e0f13ac3ee0ad6d680b65","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\d53670c4-f46a-4d49-b188-770b86bdda19\Pasted text.txt","8127","c71ec7adb5af079fc5c93536107fe30ffc0906700b5ee5eef6bd2cca1665dfde","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\d5886992-638e-479f-bc30-e327bd7a10ee\Pasted text.txt","12246","f0da2b58af2e30cc1b1cc353f3a6b00a592c800e17b8d00bd2c13dcbf16c5a78","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\dd19a693-8805-4f81-a65c-bf2af031a37a\Pasted text.txt","9346","2453530cc98ffd9b270eef47786a9d596701e4831e2a3c16c3765152cc916494","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\ddd6740c-486e-4ebf-a11e-c9687206178a\Pasted text.txt","7103","149673c0e35573716086d72f65e1b8e6c805c4f890b44722b839d4ce7e6caf15","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\e11a00e4-8fcc-4ad8-8861-2fc0244c4324\Pasted text.txt","23406","c32107c1735d544d91c1c5e6f94c731e71871c66ff6ddcbecedc4c86fd1630c7","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\e1fa9a32-14ae-46f3-ac02-c7115c832175\Pasted text.txt","8246","55050f60a15d18b119c83799231a0af34b00738f7ae8202a232a07df23f65fd1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\e51bbb68-0db4-41ba-84b3-e20754ba0d33\Pasted text.txt","37962","214044c4a4a71430ab8f271ba85256e48c6a08785da0e48ecb7507a04f23b6d1","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\e642d815-f449-495f-bd61-4b3e247e23de\Pasted text.txt","9502","5dff89adce75a8b9e0a699bd31986a1a18fd3f25de7218da2800631365b4986e","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\f003a1f1-4ca9-4193-9790-0ba7c1db9812\Pasted text.txt","5158","a8241744db40871b36d0a2b39796b7168fadcf243e02a352fa794176da389c95","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\Users\macbook\.codex\attachments\pasted-text-attachments.json","129812","6bbdddc9c69558cb97444d77b90be34a20324174289a4d7f3f337de89b8f7f85","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\portal-documents\58abf343-e1f5-446d-a9cb-3255f376ece9","9456358","11f0cab15eb6e51010952203ffa24fdc533a24fd642e19525fe4f46b17a1f5e5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\portal-documents\5c860c48-e8cb-4d8d-ab9b-2e3ea7036ce2","1834284","ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\portal-documents\64c46765-96b9-4f43-afc6-f5b730c010c4","440018","ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\portal-documents\b0ea969a-30ec-477b-8b8b-b7af82a11bfe","67067","5c69b6f189a1d3f5307e0cf7dd8224554705158a682637d3105afad615db26e2","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\geo-ine-source-20260928\layout.txt","57191","2fb8ebe44bb0f9e22e382436890a26822592e1da023b56ca392e9aafdde7d85a","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\geo-ine-source-20260928\original.pdf","67067","5c69b6f189a1d3f5307e0cf7dd8224554705158a682637d3105afad615db26e2","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\0ddc290f-423e-42d3-9d71-4d0613f7a0b7","256","44cffa4321c00556030f25ebc0806b9dbeb917cb3ceb2a8c0cb87be575752803","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\1c466353-ffdc-42a7-80ac-71f4d27551c5","256","212ef2dc1db7df9904d6eafd0b75dcb2e15aa32cfe875c6a4aaa90f3326fb4ac","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\1d2c520a-6320-4a36-b3c5-86afe674947b","256","bce07a2025490b0397f40f1fda70bf68a2a3079c126451c461f23c2a41632f4f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\4e278690-f201-4539-99b3-df9fc22eabe1","1620","091c234abcd17e096dc43df4b58303c6943c9de1f20d53aecf64d42ede08b30f","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\6bff5c6c-aec4-4901-a283-598d430bbc6c","1620","f43cf75b9137934e04ed43222a035cf84dc1d4e80740867a480c194ddf5b2beb","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\88b4b91c-dfe2-42ca-b96a-8b355661dcf0","256","3d8251075f3f377f30c6c76fdea3c7c283a26e35b47f8fa91768860087ae6799","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\8b6201dd-52be-4820-a2e8-1a0de7de6ff4","256","c81fd76282c9cbcff1118465c0725f2e8e7fe173933b52a37a0082b1a82cbbd3","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\91fb5959-e621-42e4-8d31-5871ef95b9c4","1620","d0a97bc7153146bb2cf1478d99b786536f71244e51fd04ca702e1066703ebbb0","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\9adbea9a-f909-4236-9e44-716329274bb9","1620","d70992539778fa94bba1322b6fed0ba59d5dca89c30d4b2aae2e149b0c0b0c08","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\a8a7c442-dc9f-4aa1-8f59-9665c057cd9b","1620","abaf5c018b6a9cbaf4a60e181a9da3b96e8b69036a4f88b0908267a3126c07b5","original","","Acervo inventariado; consulta/publicação individual não inferida","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\api.md","4801","3b7e69dd386de8e8b7f0f201aa6257adb383febe5ccd309362de2e2f95b132dc","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\architecture.md","6392","7d1b66c88903f546c7a2f6f18e00b045417c103481d7dd22cd9c7c6e0f89b221","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\benchmark-results.json","2160","ca1f37224f869a91a8ce0ce23dd8f276382b20feb52cdb5bcfcffc4d7a646ba3","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\coverage.md","6502","b3a1e96463dd9926e439e69fdbc313b9417aa1f112da37e82d983511b22fca32","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\models.md","4247","05b1ff348f98f572fd31ea9a5123517948643457e4bbd9511192f32a203cb8ab","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\README.md","4604","4323bb06506ee427a51475c90f7647bd336df667d07b1a44c50640a90db2850a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\ai\vector-proposal.sql","1027","3cf9134615be3cd62b7294c1ee7d8add8800975246a50c61033406af93e76bba","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\architecture-and-migrations.md","622246","488ed8672518b42619edfabb9ca7264e6ff330922bb1b824f0ee4a53dbf690ba","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\architecture-data-security-qa-product-review.md","9884","a2ffe042d64de6e47569c59034bda3786e0ed643a7d242563ed260d19bc44a88","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\associations.csv","2036","aef72b1a2f40576feb1f3cd9df382cd82729ef2569505b297e658d560ae96730","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\business-marketplace-progress-2026-09-30.md","5591","f81f76878dee180eda0d8c3cc908cfb284d22b4c1a471b98048fc0235d3dd7af","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\business-marketplace-schema-integration.md","7560","c9020d6efbe7e1c370798da76d1443ab82e98780262b6ce76394f857582a96b1","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\catalogue-review-2026-10-04.md","13200","3fd361cd1cfc8602529874e80df1c34a5b379ba75b0e1ae55dfe4a474cc63136","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\catalogues\openapi.json","11492","2e91ef5d2a1f2171e9f667d916a077e96f26020b59e592a6c26a8333e05408ac","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\checksums.sha256","5228","085c898a1ed900a5d269e5b2d5b0af2a56ada1d18e2401ef990b93d185a5e950","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\completion-audit-2026-10-04.md","14311","e6ce69bfe5ba9840a4f1d4cafda7f42aee4e69875f0e8d75d9fb017817f8ade7","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\consolidated-review-matrix-2026-10-03.md","128154","047bd4716165360af65c874766297b7146c9edfe5d97dbe5a4299faaebc42cfb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\constraints.csv","39081","61b10edeb087f6a021d3c1d54f45d7f1208ec92dfeb365086a18b10d3a8f77f5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\data-dictionary.csv","184351","94ccf2d0a5361309634356a3f53dd79c23d9abc5b65928a0b3aaca6228069acf","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\decisions.md","4196","6377ed87016a505cf37bf9a69205321ea6c8cd9d6a32214f12225c5850b133b7","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\delivery-gaps.md","8606","dbddcdbd8f1941ddc8502a29bfa433977eefdf3433ca5452643689e50287ff67","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\deployment.md","6603","389cef96440adb07a0085fd1ce386651378f9dcf42911fc1222d4fbab9665665","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-corpus-inventory-2026-10-06.csv","36993","5a012645c6633cdce844f34a4f67ca0ac3c3c7074884236b554a86a2cfb0a908","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-corpus-reconciliation-2026-10-06.md","20640","71c7ef081e4ed20e8fcf31d72b1ec777d8054af283a8636c25ef20c803ee9ce5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-import-manifest.example.json","823","7257e582d70a58dcb993536583da954049d7186f9b4b4ebbbc02bbfa5e9cf5c0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-browser-2026-10-05.json","1018","32a6a0fd1147c98d77bb8864e378e2bb95a95b74664b7b06cd1206ce80021ff1","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-2026-10-06.md","11706","a0e41142c688c7d33578e4f43e213112351d56389f4d1aacc4511eb4e48773d4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-browser-2026-10-06.json","1873","45f0595624860c804929b10ed46f04fdaa4c811bf4c144ae60d88b9280e8e0ca","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-desktop-2026-10-06.png","104742","cd4cce9587832916b9cc48fe0e417307eaf9264bb0cdfee1702cc9852a27a4a5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-mobile-2026-10-06.png","98371","991ebcd793ecc567ebc263896cfd6b6409317e7929f2a88a9deb54ec08b2e403","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-desktop-2026-10-05.png","99244","a6bf38faee150217fd01e9224d6fa3ab0bb9c77b30ed2e72d6dbb06e64dda4eb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-implementation-2026-10-05.md","7296","af56b14093af5faa0fecd85d1221e324602113d838619bde7696942f8bf7f330","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-inventory-2026-10-05.md","7232","8a8eb56d1fb87bb86029698579b4bfe1b4385d9dfc85ffa775c82d489a47d1b6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-migration-desktop-2026-10-06.png","99244","a6bf38faee150217fd01e9224d6fa3ab0bb9c77b30ed2e72d6dbb06e64dda4eb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-migration-mobile-2026-10-06.png","95291","5ad43f381b171ee443e866c1eb1a8f878d9895a3f02a47dc3c237c6a8294b4a9","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-mobile-2026-10-05.png","95291","5ad43f381b171ee443e866c1eb1a8f878d9895a3f02a47dc3c237c6a8294b4a9","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-library-schema-incident-2026-10-05.md","4638","e10f266a46a5af3e092761d4b0784ace0ef6da2dd0249c09f2254c598112f357","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\document-requirement-associations-2026-10-06.md","15749","60e8f9fcfe3b14042cbbee3cf1c72deeadf8f30ef3bc77b78b964557dc98ba7c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\conformity.csv","8588","81e6f0451dd5d5f526c8b7c9a78f61f6293ceb5eec55d4b5ccccde40daffe7b6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\decisions.md","8747","ae144e7594d0e730dc62e0a4754072c09095f4187df8de9e5d585872402f3b1c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\entities.csv","22778","ad66733605c17455a2c03f007ecd1f9f26ec71685d60ee73be959bfb53b8b958","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\examples\gap-calculator.mjs","1523","70dd4a73ba2b5644e66b307279141bfe6a31cd9c991bdab8a4568a8507787d95","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\examples\gap-calculator.test.mjs","2509","eff94de4752e056babe877a008edb0007b123fc5bc87019dd78b0699081a7293","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\examples\package.test.mjs","4736","0b7fa5eef2359f6c86a504f87bfe0e15ddc9b2616668c3be61e2ec1cec65f985","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\implementation-status.md","14670","08243231dcb0fd618af59ed123943e22bf985f2e4967a9ecf2e7e67bfe401198","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\indicators.csv","14969","2cf4a982c32befe5d703a332b9baf9ab35d91e53df47c9af0766ac0b94faf796","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\migration-proposal.md","8435","4983843c47a74ee206d8a5b697581f4288d81971a6452f5b438521ee6a3d44f4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\nonfunctional.csv","6333","51ba1bb3767bd2aeddcde2a88da6c373a3ed98a1082addacb05111a7950ef170","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\openapi.proposed.json","32636","5b4e76561f11ddc29bf6c1adf46fe2d923601cf62b1869b119c246f60a992743","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\README.md","7951","5bbfabd1ad0b34a05ce23afe2d466e8eec58c594c7345d2fc6380469b56b38a7","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\requirements.csv","22521","ac4d0da696fb4b562e2a832cc33883a9a870c5b4f730eadfdc0e652ff3fea9ee","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\skills-education-schema.md","7588","89276898fc606dff493724c3a9e33beb0be9dc7ae9448253d4ad6685052d30db","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\skills-functional-diagnosis.md","13135","8a271c555b67012f0e50ed71b5edaed8ffecf67919cd1cb6b440dea97d7781d0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\education\specification.md","63304","0419f22de21a328a8407660caab409695c35fd8868580a2e3331f35af45a85b6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\erd.mmd","24399","7373bf93e95db348b63192997d78ba1ce8414c95d6011c58312806022fc6e974","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\annex-de-execution.md","4387","8e5504eb242b54a8915c14d50f7dc4762e43df4fc7d3cdc353fffbac32a2ea2e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\browser-validation.json","723","4295fbe5ff0ff45429acde848f8af5632f15590be0114e3d6487d8b435a209de","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\canonical-integrity.md","3028","d9f89c386b9df543f8dc2099823a52b836d582fbec6e6e67e2b528b5e1759f9a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\compatibility.md","6456","9372a6be5d1ca7a71e98a032a8d3092fed8015e83df479f50999a4b90ffd403a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\form-schema.json","17645","45c3a18a7815b0cb29bc11a16a0a81ef3b692b38fef06664fd1024547b2f06dc","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\implementation-status.md","11833","6228c332b325cd9b71860db896c8e1ffbb2ef6c2a47f5792f0bf4c8e41ab3cad","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\openapi.json","134052","4c4e42306f85e8ea26bda21999e3b21dfc8560ee18f34c6cad0795ec9cea763a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\phase-1.md","8409","a9271a278e96034cb14189fa8169e0a5203df81933eabad59e4ca666fed9a44b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\README.md","21344","d7552eef64ac2628b9f3a81f219241205af74f2fd26796bdd3a5fbe0f600073f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\traceability.csv","2535","f5d449b5e317959bbd12b67a39faff1ca85cbc3e2395643d30dc9b0e035ba057","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\validation.md","4768","86514166a31c99a8d57531805ca894952d96491db0cf2a914b753ff01ce40584","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\verification-evidence.md","3874","f7535a947c9a92b3cddfcd4b3f6865b2123e7c08637fa99c0a28ea2de6c2a33f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\wizard-browser-validation.json","499","c177700ec3eb8d31a9024b83abadde343209a9fe3a14f6f6071ec8ee8c319f8d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\existing-business\wizard-implementation.md","15735","fc3aca9367dc714e0ec6771920aa1c784a212e1543b09747ba9e5cde2bc4e356","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\fiscal-source-references-2026-10-06.csv","9992","f2fde2257fd481f984e59bdfc62ce209c849b350961111616d2c2927c1421d6f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\frontend-integration.md","2619","a4250eb4d56c7c4a1893d974c72a1a6e423a09d8f5aff9498deb5ae2ea18efce","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\ine-import-status.md","7359","1298c29dc6aee460d03b45b0d1c883c81e2a123a295ffcf1b5de30a8edc3791d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\interactive-map.md","5607","5579a82b0d1008b6b5af034a8c216cadd3209e840de4f7f998545036b49c9a2a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\investment-dropdowns.md","5831","76cd7beec972a010fb17c3fd1f65cd6b268d8c3b5fed1c8fc62c54384f1624ca","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\map-coverage.json","2755","98475bf387143b988df9fa69f0453ec6eb6d93262716bc5b4d9b0d3cb6d46f5e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\opportunity-dropdown-browser.json","2924","dd605b3db0cee0f5a14b7260878a723bbf1b0bf55fb5af3a656d245fb74ff5ad","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\README.md","17375","c3d14064c552f338e4ce2480110a7d8dab4657f23b9f075a997f50edd2ff82c0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\source-manifest.example.json","247","cfd02f4c01174e799936234a897e65a6707c85217ebfa065e3805f56c20d2923","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\sql-workbook-inspection.json","655","c44a6edd502134fd6500b1907e81a1134560d59136099b9a6d843ffc91b09e46","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\sql-workbook-validation.json","787","42f0b796c911bff0289c19bba0683cf45d88c762b75bf54f9f9b730dff07a584","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\territorial-mvp.md","8069","16b46d4b0a66031f25701d2a8cc4327a0b43abc24f6db53da8d7394e04e8a4fd","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\territorial-openapi.json","49691","e0e27e7650f43b35ccbf9491e647aa744c860bb2a323fcfabb389d9a239dfcd6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\gis\territory-integrity-results.json","3783","8062e5d9975f6e8d16083b9c8ec06bcacba1add9d68de3136a99001e39a9a3d3","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\indexes.csv","40127","142728247045678e5f026cdebfed7e4cd69ebc637680b91380f4d3e0f7349dd4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\integration-repair-2026-10-04.md","12760","44d02093f1a97a006a18a9a7a41a9d093d6afb89ab1f128f893c3ca290eb83df","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\implementation.md","6487","84321b7d69d01a2eeca04efca0d791a204850e215c2781ee90ade882d14e26d1","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\legal-source-review-2026-10-03.md","14376","f9030854e6fe69b636ab61951643a8f9fdba4b5100eb454836eaa0a423e67e38","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\requirement-traceability.md","15535","ac3b3137123bcac34b4390df26d1474eb19bea8d6fd5ee0b156efd58d9a7ab15","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\source-inventory.md","8648","cbf0a5b0d55668f6ce18a3a03fd19478a2868c32482e2afc2dc2115ce37c4f99","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\legacy-schema.json","52671","4c6982432c7451d144ae1b03a8291e7796c977f698c8b809b57824aacf5d3629","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\legal-source-library-migration-2026-10-06.md","13327","ec3ac22cf2a374777c875e1cb46906596dc49b685fde00f6110f5f87333af38b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\malware-scanning-2026-10-05.md","10742","914b859d4cd1177e4085f7c96f59545de3e53adb6b8ba16ba725d4b84ddbffaa","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\management.md","5709","5d9e3c898949d510858a0eb6697b3b40c2d3b786ce063e3d1b2d5115a38a5ad6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\objects.json","10834","9d7613c948de2b1ba6f70b97472ac9f06ef445fb4d82ef1eaf3ca67dab239160","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\browser-qa.json","405","defb676b16f21eced0f715945a3fe770b63c8ac065b0738d9b4f68533f3d9249","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\contracts.md","3509","950bf6c89c0ab7f02bbfe804db4950a44cdfcac94af615aa1ef239aea517f2fa","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\README.md","5068","98c3be76059731061d17a8a2d5d3d33a3316331aecd6d37956bc073d9ab6c76a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\requirements.md","5339","17393cdd83da8ff46cc0accee7ad9465679e8ae7c7099897bf61a164fd1dfc18","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\room-1440.png","202889","5057540714b81f4618f0ea150febc77223d3fa91cf50050a83d18fad8b4b3501","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\partnerships\room-390.png","174441","754f21c816f960c1db6d7035dcf6ecec7c24064f43627deb08b31432a4b4394a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pii-extraction-review-2026-10-03.md","8638","d606cf522e8be973805529bb341c8a16d3bd70f161a5e97ec01324c25dc7f9cb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\authorized-opportunity-filter-browser-2026-10-04.json","915","b67e04eb2c9660ac23b74edc4e293d2bf3d7c5f9bff5527f9436a015b244c589","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\field-usability-pilot-2026-10.md","6408","b9b820c39bc4323ff19b9897b9cc533a38d76ab943ee9ff84054f62e0bd7f967","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\investmoz-catalogue-guide-browser-2026-10-04.json","2850","e5bd7c71a23a9bd7f6f5b61188cbd995b8115acdd7a6984b711446262d2d599c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\investmoz-guide-mobile-2026-10-04.png","326034","b5512909b6493b60013035187c950a7b396d5dfad8d3aec1099e4719da42c0f4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\private-dossier-association-browser-2026-10-04.json","343","d14327e8c37cc160cbc8ded3602970dd1a63932389984d2731777ca92f84f9bb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\private-dossier-association-browser-2026-10-04.png","417060","1e39c9a6bf377d537853024481d4e2d92a3907e185f51a89c695ef8abc3280ea","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-filter-removal-browser-2026-10-04.json","446","b3e15d696dd1c4d8fd3305395c48221971112a1579a5ea284edcdf32d06e42dd","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-filter-removal-browser-2026-10-04.png","447090","e9a1c971179fbdfaf95b4ffbb49f79eb5d45658c1c163d758dcde5cb305424c8","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-browser-2026-10-04.json","1595","8bc6045b45eef8b2e051b77f9c809517b29f1fe2b4f5eb1048182b930a48a05e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-desktop-2026-10-04.png","816346","c3ce06800fe438e481b11ea58c47e9c9a493091c4c5a303f2118c6c23d87954a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-filtered-2026-10-04.png","467961","8a31415585275ba6bccc623f6280e178c91e961dcda3037a51553e73d3e647c5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-filtered-mobile-2026-10-04.png","298053","e923261b8ecbec431a060e7bbcf49c95d43aa3e90cad15764d27664036179e26","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-followup-2026-10-04.md","6700","e7cd4e5cf3372aacd594da39bb2526c9bd393428a96e640594246fb515aa4708","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-mobile-2026-10-04.png","717500","545d3e39fcdbcdd9a24722d6d569508b410a1e9b2ffe96c7b63ab3b6675c8bcb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-browser-2026-10-04.json","987","e8023c8df2bdff4e29da8ee9cc26f035af9f18b5a48bc54b85d0a16013d5a347","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-desktop-2026-10-04.png","480868","af393579700ed3a7f29bc0ea06ff1f0316e2af6dcafcf8b325b1afdf721add30","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-mobile-2026-10-04.png","367616","8afbbed084b57fcb20298d7aefc478336942b3ba7a0608287bdad34388711c30","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\portfolio-journey.md","8763","079dc2d9a5aa5384cf38680eef60876932f9e0a2e4260aa7a6dd8bec3fa6bdcf","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\production-reference-seeding.md","2422","b4c9585fc9470b1c0fc323417083c40cd9dce98946731c55c4e5a71a88a6bf3e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\public-portal-browser-validation.json","2180","7a30088ef81871d55d93e0cc3a348fd9cd0a9afc772bfb61572e829dd892561d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\public-portal-sections.md","7820","1b0a213480a9700f6f0dcb68bac5459f2e0af9cd274f2f2f43e62750e3d0f81b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\qa-database-target-incident-2026-10-03.md","5050","882547616032a06c6e876a0ef08e54d36018990c1f71d6ae6d4ed4dcb23969a0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\README.md","873","1cd4bfb21be5cda9bf2d66574ec05a71d1a7cf3acf4e78d2403cfc708b6a7ae6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\reference-schema-reconciliation.md","15940","0b3c93bade03cf395e5400d30e1d88da25921fbd9b9c79d180574d2b0d2f78ec","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\browser-qa.json","489","43df26a5719e03adffc463688313c0ee96536901851101984be6fc35c4ed035b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\cluster-1440.png","463640","bcf2059a862a3ee4866d05870eae80c0af9aa6b9a831b66d3fd94a7d7df046ec","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\cluster-390.png","256636","907b8e5ac1075f4cc8f4b34caf1a71170e68d8ff031e1527a8bbed9836bf541b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\README.md","11108","9794868e15c530a8e5ce1b5c16c8bdf6197a6c5526da2aaed4350ede77e27b5b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-1440.png","371150","914ce5df89ddc4a49d8f283041da3b21aa46a22436348683e78c08481e6f20d4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-390.png","341234","50504637502caffac0c82097006d8f526e8ff25d1d922e65008236abef490895","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-browser-qa.json","284","26d1cde41c7a1be0f8394838917d627698ec2185b4ece095d365efa1a8c7e6c8","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\relationships.csv","11815","e236a15a8bd8b55ae2c7c74a7e66185066ac24708344f5836ebea88545a544e3","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\remediation-execution-2026-09-30.md","14937","c75582728aeb1d1490cf9a007745a87e540ecbc0f5082c7eb3ef4be85a7e8e5b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\requirements-audit.csv","57329","522507d7b2d491ce63440a7c9822d28adc41d8630e1136b945b3671ec55f7ecb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\requirements-audit.md","17494","1fc38e37528235a75789c92842995739474be58d96fe77bd5daecd1a449d8f88","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\roadmap\README.md","5113","df844466ee6e4c2a871191bbb2a3038b59d6c6fc307e42d27f434cfdbf60e5a9","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\roadmap\source-inventory.json","9580","348b0b2153cd9134d0cbb5f2604f6bca89c0816fcc6b078f96c86a77d6104891","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\runbook.md","4965","393bc08a00e6054d1881a256663ca25a487acffc16405b35441d5ac42da3a7e8","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\schema.json","419778","8881545beb64f48c7c1afe97d24744054bccfe9f698861d809c8e714a3bb29c4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\current-status-2026-10-03.md","61546","09da758c9d82751c5ca0edfe0656d8efaaa0c610ea3c6f1de45ee6dbccc0fb50","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\data-contracts.md","18346","714ebb4a4215af491de89a7251ece2db3d5b25f4770fede1a7b4af41614f4dab","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\entrepreneur-question-mapping-2026-10-05.md","11451","b374e20193ca20ee2b24fd53ab4bf4bb9c716bd2b519e2c6f419a4fe4eac9f70","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\fiscal-reform-2026-review.md","49068","b334895e6647c6776f54488fd03afd4e199f6bf6eb8c9ba4db52ab977f6fd618","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\investor-project-journey-2026-10-04.md","3839","5c3dedd8a32d21eb53c72172dea45b3760aaf62e4d8076ff71cc86a95370ed46","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\official-source-register.md","51676","8ffef016d4bcdc045e3e3f4ff827d1b014736a91fdd2139fabae88d70bc93a53","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\openapi.json","79479","a5ebb2ade09de0a9b620b58b1c1e3c14d0745505d127b563bd178bdd322948b7","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\primary-text-review-2025-2026.md","24783","e0a25324df6742dcd2a0b4ac57c79c86452ab87a64572893befeb321e322d78d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\project-dossier-print-qa-2026-10-04.json","894","bc41af7585ac4444b5fbf932c0dbc45a7740c6915555c0ae279c9df317335d0e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\project-dossier-report-2026-10-04.md","4989","2fc15d456bd12dde01b7dc1b287b30c4bed509a97b0c26f272088e291cadfe21","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\rule-governance-openapi.json","11400","fa52572acfb7703648f2590ca114fe6a6e8f53b64d6bd2253281f4f121d26bb6","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\rule-governance.md","9038","9fe043cd46258e470a30ba066245aa8a2a341821a426f0ed95da5dd2a7359896","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-after-forget-2026-10-04.png","119300","eab0f37d1c013c6200e623edbc46c17647f5a34dbd06a242f7942ee6bb9906de","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-before-forget-2026-10-04.png","148320","b57b5cc5f2e8b84a882230a139a660ca3412a4f67b766ac6d8d315ddff9fb456","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-browser-2026-10-04.json","1440","7fc66d67c69b862e2adc85feb897c07b33516089136781acdf3bc8ca78294e8d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-incident-2026-10-04.md","6347","5f6086944e6fa6b310994e34ca32064e202f4911230cf5cab34441039dd61a1e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-a11y-browser-2026-10-04.json","3689","258c9e80b028ffb0ff6e3cb723c1cd6671dadc289baffce32e97e42771fbd676","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-api-errors-browser-2026-10-03.json","1598","840abac878be29b36cae7699a6fd764677ac75c902ab6d780ca009d1f3968342","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun-qa-verified.json","3689","7b34046113d90a8fb3078c51ac9f96b74f74720ed90010b389e09f201a705957","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun-runtime-verified.json","3689","5ef9e5c31795c6f0304f1483864f9c2ad685a0bebee59078f815efa7a7b7d3d0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun.json","3563","520c912342d25ee8412d969cae15d9745969f657709a31d042511a0915924d89","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03.json","3563","8671f4f23d1b55df0876de13476781cba79467ea9061e81814b0ed879f30744e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-calculation-browser-2026-10-03.json","2859","f5f64227fb7d5322e4a184e4a05052d032a4697d660cc86b0003514825c88092","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-calculation-responsive-browser-2026-10-03.json","37757","54771a108906d96491144df69933a4cc0da8cf125d2d88e367ebba38f4454397","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-cashflow-browser-2026-10-03.json","2978","4e78a67cbee67c1dae4ab6b19dd8e63b27560bde00deb8c66a3c868c8cc65146","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-continuity-browser-2026-10-04.json","900","30f261ffdb7f6e10c7305465166583820530b534f87933049cbbd3ffd281c495","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-final-validation-browser-2026-10-05.json","4293","3ecd4b3f1d2c212e5c2cc4d44270c25ba7d7b5c15952d89248f38b3171737e6f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-journey-browser-2026-10-04.json","4078","98af71bd0adbcb6729da7519d0a41457bb9b86c34568935fd7d57fef0dd8c06c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-248-I-Suplemento-1-2025.pdf","440018","ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-89-I-Serie-2017-06-08.pdf","9456358","11f0cab15eb6e51010952203ffa24fdc533a24fd642e19525fe4f46b17a1f5e5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\Lei-22-2022-IVA-republicada-BR-250-2-suplemento.pdf","1834284","ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-extension-traceability.md","6420","ecd8707ce939223f27245b88af75d349ff054582b92f7edf63691b5a7308dd0f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-gate.md","22365","e103c93808d7291b52f392dd7a2bf5bde8e1a1585d2402539f25f1e0c5fd270c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-technical-traceability.md","6748","21add6ba1bcd9e9229aeac7b3a1fb605186e88728baf767ebb9aa17319826c8d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-11-gate.md","7188","41015335082056a3fe8f0ac8d0a08512fb0d6b449a48a40a549f8c2cacab7c80","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-6-technical-traceability.md","10008","b651581dbbc9a4deebdf29306ddc41e854a8b94dfcda46f33f9ec5b2a231bac2","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-7-technical-traceability.md","11008","5c0ee04bfd55cb0a594af0234385f849fbc1b784b7a49345213419388deac582","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-8-technical-traceability.md","8036","e776a33e000f1787d7ac71616b0b2832339f5e8242a553d650f7c7310df11223","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-9-gate.md","6824","da2048d365ff9721d1104ccfdec10dc8802b8f02dedb1a3bb6e5417fe4d4961d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-9-technical-traceability.md","6063","80d4adb5e4da8e6b740d6343332869c5d6d1a437bb213c2790a81ed7356cd560","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\simulator-evolution-progress.md","273004","625a0bcd98d72617656ddb71679e12fca2d3ed23a6bc55782c32ae972c8a2b9f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\source-reconciliation.json","372","53783524c4eb928cd1eaa5c575a6f45fca4f1dee8b3aeb0be6d874807e177748","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\source-staging\pii-26-30-review-only.csv","101415","a46e658cacce19a387fb314842150693f4020f479ad14192282205d5e71ce3c3","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\source-staging\zone-integration-2026-10-04\Pasted text.txt","9346","2453530cc98ffd9b270eef47786a9d596701e4831e2a3c16c3765152cc916494","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\architecture.md","13447","4a282fb574af39cce16a5f4f14324699bb13469c8639a221464232718ecf6597","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\client.md","7995","9767c99c96c3660fcaa98f39df1db58f47a6bb5a802c4ea966fdc26bd45068ac","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\mapping-catalog.md","18692","39505269ba8cec49cf0642e9b603a31912a1ba0c06ee2d7969cc21333febc6a0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\outbox.md","4795","3c0bde5e1dc9e0352f060ba37d58f822a7cc1eb1b2df52fa881928e088b05bbb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\table-catalog.csv","9934","45ef0a893111afd342963d8240ca17fb276a090e92efd1ad2ab41d6a48c8e9d1","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\territorial-search-audit-2026-10-04.md","7237","704e41a660afc1eb774d6320d5681ee5f348aae6651d3b5cae3c8989bbe38d55","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\traceability.csv","88017","4ad83685122a63d90c77eb2c1be2858861b61bdde4c2300012734482af77ef8f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\browser-validation.json","5045","4ca6419b44a6fea847212916af59ae6672c0ad062cb2daf535acb2a90d15f0b5","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\data-and-operations.md","14690","e63e32831b0dc4172f1b7f4a028c45c3b2de99dfdaca6ae3eb408a426cd9cba4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\local-latency.json","952","ec0e2d6f35b02d87c1a56150da7135efa6067c11ccc64582e15e2275b33be92c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\openapi.json","191844","ed1ba3868a71ea1ca0f6e2aa8f0ac5199dd60dfde5cbe6e2cc359baa4ff9cf0a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\public-browser-validation.json","2615","f18a29cf9b7ff5978ca2e7b4fb53dd624de5f68a2e573c0282b52fdea94a7bc0","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\README.md","9760","1dbda44d61d217f0179127fd128c2daf5bd5028a28f5bd240f3113f2a865173a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\traceability-and-manual.md","13614","66e5bf20cf423c58b923753290e30903265905a2eac69995777296bd19757d6e","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\unification\validation.md","5778","999cca6894fe87ab0f579a1d248764a2af5a412049536cea51db20c0a07aa90c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\upgrade-progress.md","13050","c33a1d528fe234677f267cd3874c83d87bca5e2fdc143f20c63306ab10297fad","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\ativacao-rastreabilidade-territorial.md","12206","904787c7040c29f7410d599fe357319afc559baba5c68dc319ade17d21e801d4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\ativacao-segunda-entrega.md","8837","c8acd38715c26b13b563afbc8ee02851c929af9448d2e78cb1656d16988803d7","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\backlog-mestre.md","49028","8bcc5e66de95426dbb291d8a380e86d0f4a3ef0e3e70b48ad6c7d9e31893c7b3","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\consolidacao-nove-diferencas.json","10320","d9f474c0dcae06e78b71c720611b16a2a0ec0d6b83bfd9c83558781eb130f0cf","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\consolidacao-variantes.md","7958","3defe7f46aeaa37da2f06f5c358da83f48ff4656566d4044bfe7cfb0ad50d5b2","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\ficheiros-primeira-entrega.csv","15338","b8c6eefb8fe879df7637bcda4aa4d458254edd82aceaa86991b5d885c046ee0a","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\ficheiros-segunda-entrega.csv","3345","a7445854213ad91cf5a929237dc7c2ab2f2f682f5eb014cd10c4f9623ac30d20","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\gestao-oportunidades-dashboard.md","13951","a12b57985e779180860983968922941bac9db3ab91aa4977d4ccf2b5b6d74997","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\indice-documento-mestre-atual.csv","151889","35ffb5d727f8ab1811ac946c2f89c2e95a74108b9a9cfbdd688a29fffee6080f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\indice-documento-mestre.csv","153757","4c13f1efd25a130c0d63e4a7f2efd9f9c2fbe9eb7ddee452534f06e8d7759bdd","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\oportunidades-correspondencias.md","15378","3812fe47bf667a5323363cbfc7c0b329c1f717f4ea814a6e3c454e6624224a72","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\origem-oportunidades-e-separacao.md","7039","83c37556b898e3e2f52b272f515d2e10830218b133298dd7086c6b380bae418c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\primeira-entrega.md","12287","91af08a26aff26afd420c3fd9164d391014ef224b19db5dbe0f00758a2ecc571","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\primeiro-percurso-ativo.md","17401","432b134b6aec7612776d510fcc9c38d8d566eadf821928994b60ed717e0eb84d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\qualidade-territorial.md","48392","6bf7866d3946b6c99f8c3ba2c6bc0b633d54d4da5b9369a4883e06d6e30bffa8","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\reconciliacao-documental.md","5009","dab706f8e0b6a66e6cd3fde2bc8989d9f56bd6ad3f4e34f9fec52db6e38eaec4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\reconciliacao-fontes-territoriais.md","97710","3733136a7a2696b2cea4e9ac4ba5e0891369ff8969497ed87cd2962084323ee4","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\recursos-oportunidades.md","10792","7829ad26ad1060710426706b05c9dfbdf1912a08ca190b23c8662bba5827c632","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\releitura-documento-mestre.md","3985","e7f743c0e28a07146e391e20675360c52ba9272cbc4875e8d74b7116946e590b","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\repeticoes-reconciliacao-atual.json","235914","9166ebb15935153b33f60021a8b008ab8479ca0671640af28a9e87138bfd5758","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\repeticoes-reconciliacao.json","278145","1f49b0ae5e4cfd95c60011d6af4a16a5d6f7ea2c13446ff1d5224ea66343fe59","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\repositorio-legal-jornada.md","3245","1729692568c02aba71f246e20e842175bbb78795645f762091e679f3fe77b056","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\revisao-funcional-transversal.md","11226","90ed3ac0021863aa92a864e1cef754ec45e16667f595a7fd26f771290325e44c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\v2\revisao-origem-oportunidades.md","5942","1feddb2d78b8a04f2aa46151784a3643ceea08b7f9b52935ff336745263a4cdf","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\validation-results.json","5131","8a35788bfda5fd7782f269f60c963b909e152d55880d3d090cc960a5d52a8605","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\validation.md","2958","b9d1ec9d4f8f8879ce9c650a8ba59a811065fe7b7e3f53f201fb64151533fec2","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\verification.sql","1732","d15685b13971cb526cdcef65c8511e79f9de7da28074450dea1bb5654bc69596","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\baseline-data.json","3528","72736fbe37f8237fad1ee0a1f6dd97709c8d0464862d2635a6ef51c6bf8b18fc","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\baseline.md","7117","db6df0dff91244ff950acbc9a285b4bb17038d9514141e236c12286cbe97b617","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\browser-validation.json","2976","b89e20bb6f0710e9e1ef0e7392790320da1bea936463a3bbc205dc9b2016c12c","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\current-data.json","3910","81d25d5de6f22a01c55b8e945efd6626c9ca61bf9039cc93995ff00cbbf1a9fb","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\data-dictionary.md","4418","d851147c7b36b738a92f91f6c697e49d4b5855ce42a474ffa9e672c90f445986","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\diagnosis-and-adr.md","7962","c5a1a40aa17d2793d5c529a634770d2ca3f934ba18677703d741ef800907935f","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\implementation-status.md","7694","263b86d4eeb98c7996674a0a26e070c50c4f6f7638ac1c4d810262ac0adafc19","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\industrial-parks-reconciliation-2026-10-04.md","12705","b6aad32e2330edabd8f7c06e7cd75dc7a8faf5dd1be657676e9db5670d1648e9","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\integration-2026-10-04.md","10944","a74fe74d871f0692ecfbfc79a62309e0fda9bec5cb43757897cf589aafbee076","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\legal-matrix.md","2918","1178627b7f57c31e837688360cf0d2dc02b010a0114f3a8007c25e7fa843c0a1","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\openapi.json","93753","314cc7171e75d37d22afc9042e175db71b373bb94c0d1becc4c08fc1a73d414d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\operations.md","5020","d0480f301875b84f144e272b2a41c67cf2d13bc15ffd8fb5141e8d4c5c584f66","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\phase-1-attachments-qa-2026-10-04.md","6110","abfb7a9925886f5c4faa88350038f13babf8cc2bc27cf49c1e9e9d92db700bc8","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\plan-and-traceability.md","11977","4516ea21664f2c0b56f5185515b6e05a1292377a92d0fe4123b1ed97639f3c10","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\README.md","3529","cab2d4152ffd7772bab56c5caa98261ad497be58696594fc9e0d4d9e909aeb88","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\validation.md","2987","bcf73cbc4ef5ef4660ab008c64f348ba3c2e3d77d15ec0c04617fe851d11080d","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\docs\investmoz\zones\zone-catalog-active-empty-2026-10-04.png","79809","285108e8ac37bd2ccf546d67f72d9f73aed3f9ff26597d68db0ffb514b163855","original","","Documentação do repositório","Nenhum cálculo ativado pela auditoria","Situação documental não determinada por inventário",""
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-adm1.json","15442","41efdc512ba971d6ca3b447d929e04c86d85ea8af1dc6c13bde419ec4533e448","original","","Metadados/candidato geográfico inventariado; seleção e publicação não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada",""
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-item.json","1513","4f95009b98c7979fecfa0986a38bf77e660376f98bcfd70d7369bbf363298af3","original","","Metadados/candidato geográfico inventariado; seleção e publicação não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada",""
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-service.json","5929","67168029d5f559d926b8b3c432729a8973cf1dd2868826e86d756a0c53c2ea4c","original","","Metadados/candidato geográfico inventariado; seleção e publicação não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada",""
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-source-search.json","30681","247f600f88a30a7052c62b489d98889e49f55f75759c07d3f8e992418ef5cf0a","original","","Metadados/candidato geográfico inventariado; seleção e publicação não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada",""
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm1-ine-20190607.geojson","5254315","ce5cd5f6090b7ba9ac78f919c9dd149f6c7880ab8275051a3398b1c6593fa989","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm1-ine-metadata.html","5769","de118cda24c594402adda6f11143ce236f928502b096cca45be7f5897b3ecbcf","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm2-ine-20190607.geojson","18086741","16781986ac938bc8e81c9ca01a076b4bd46e333e8877645844d0cc7cd2919707","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm2-ine-metadata.html","5958","5df480267f2bc98a734d6a0a9b2531ded59cea715501006d2f869c35a12cd420","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm3-ine-20190607.geojson","26773796","ef11737c1ef68870bfcee67903352b7e554cb40ca39dd85f020c2a13631e1635","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm3-ine-metadata.html","6063","1366696c41e95fd3ffaa7190764e7bee82ad5cacc062d9f66b74090bb0da7431","original","","Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada","2019-06-07"
-"C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\unfpa-moz-adm1.json","15458","a723d8745e6c1b66f5b374839dba9863ead819f2e65279b1bbd32a8cee8db47a","original","","Metadados/candidato geográfico inventariado; seleção e publicação não inferidas","Nenhum cálculo ativado","Vigência atual indeterminada; edição histórica preservada",""
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\O InvestMoz deve funcionar como um assistente de investimento orientado por etapas e regras de aplicabilidade.docx","1327814","aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364","original","","Exemplar integral lido para proposta; publicação não inferida","Especificação funcional; nenhum cálculo ou regra jurídica ativados","Documento de programação do responsável, não diploma oficial","Exemplar identificado por SHA256; data/edição interna não identificada"
-"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\O InvestMoz deve funcionar como um assistente de investimento orientado por etapas e regras de aplicabilidade.docx#word/media/image1.png","1288315","1da7d5a84162f3a4772e1f58a5dc4af701694e92ee3110a6530288916f728d80","anexo embebido","","Exemplar integral lido para proposta; publicação não inferida","Especificação funcional; nenhum cálculo ou regra jurídica ativados","Documento de programação do responsável, não diploma oficial","Exemplar identificado por SHA256; data/edição interna não identificada"
+Exemplar/caminho,Bytes,SHA256,Tipo,Nota de leitura,Disponibilidade,Uso em cálculo,Situação jurídica/documental,Edição/versão identificada
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL2550.tmp,451286,0ae1dc970cc219a57791483bf22f134b2fab1ff5a6d3cd98eba98a5737f23010,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx,6005783,ece2c2edee8df625e712ff9f285df5c787378fa3477e466303b5a46ee0971c09,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image1.png,1208097,1495ef144a048018723db1c0e11217fa14b4d7b14d8e65e32a3adeea23d08c4c,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image2.png,1302649,fe235f3c808f5c0804023dd4c1a079310bb2806806933fa95519f923af759f34,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image3.png,1155707,d791e296e6436c52e52d3d29954a83faffde2f8a1228ac48a0aee9753aafdb72,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image4.png,1539,f2f900bc7dd199be5f3e037424a5daa0e2865b46fab8f5a24f9359df1594e144,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image5.png,1180837,9e28b4fb57f6df624545f1ba63b778a7d5c92ea88dc5d4c6cddd97d1c9fe059e,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\diagramas.docx#word/media/image6.png,1134030,dfa0c37b886b5fd9df356f4b2f3c24a1199093abf8fc60dc2ed335e4bb68dce0,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\FICHA DE OPORTUNIDADE DE INVESTIMENTO.docx,96615,d52bc22b8646f64e5ddb70811793f7d8b46197f4665b6577c8b25b1910ab4768,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Necrologia.docx,53217,21612c9490cf1382e5c1d4499a10d785f8b9add70322132f32af63449c0f1010,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Roteiro de prestação de serviços.docx,16405,3710e58dad14e8bd6c6aa1eebcf1d21fadc391959681a9f0fa6a139355716fea,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~$vos modulos.docx,162,076a465696c65ff00fce492da12479cbe10d1731e38ca12d3ebd4211111e0fdd,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Guia para Identificação de Áreas e Corredores de Investimento.docx,104659,6e8fec17b7f6efa2cbaec46abb9c67b37693d350a5e3d540aa362a769ccd5ea0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Guia para Identificação de Áreas e Corredores de Investimento.docx#word/media/image1.png,49813,c8b4bb1417aad29a159c3e5e9576e726a1d50aece731d8fc381238ff3a0f2b65,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~$oposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx,162,6ace089e8d5e3f734ec77f9e93cad87834ae58892871fa0b6f98586e5576bdd7,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Agenda2025.ptg_.pdf,1064241,6b7b13eead5191bda3f0318941713dea16fc6d57bbc61ad6f1f3c9efa67672b7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\MARP.pdf,490336,4884bd925ddac14c1c490b822d4ebc391e121df6bb64cef4508ae713fdc59625,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\PENSAR-MOCAMBIQUE-2025.pdf,21361335,d70450b6dc90370bd4a6730d2dbabc3ae1b33a6dd775de1b3b983744d497fae5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\2026-RNV-Report-Mozambique-1-1.pdf,5686850,305387a6def4f1646644a0a50dfd27bba4094d0639915b5371e403253230e8dc,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\ENDE-2025-2044-vfinal.pdf,3667603,520dd8ec3924321f69d3d58466aec833cf321b007b31fc8dc7fd70bd49b0d42c,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\RELATORIO-AGENDA-2026_July_02-final.pdf,1136956,9ffd1074a438d59c6978c8da36fa777abbb351a3c2039dac0fef118b3749ad87,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\CMuendane_ConfInt2026-MPD.pdf,636021,708c5a38cf04438ce371f1a39ad2f5a13e0b78f3e45b86693f5a963959dac2ac,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\JFerrao_ConfInt2026-MPD.pdf,781278,7debcaad44e8a2df8cba70256b519f4cbebb89454fbf3e5fe7ac0550e74297ae,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\Apresentações\PLatilal_ConfInt2026-MPD.pdf,326252,8690da2f9ac9d00e3c826ca7119368c17e959b9ebb945e74427085c2be02d714,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\conferencia\PORTUGUESE-Mozambique-Special-report-2026-vf.pdf,6768008,c1452219bcb608fb4b0fd51f60eeb676d09b6ba867f43c3178466b01c0783c44,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Capital social recomendável.docx,17137,3b86ae01cf839502792fb130eafdfca2a0a0b6cea10d7f445f972196de766ee6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Para a actividade de prestação de serviços de consultoria financeira.docx,53137,bcae28d5437bca81d6922678051424740e56db2fdb931fc7653966b6f04e2361,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Consultoria e aconselhamento financeiro.docx,24096,5a1aa63b95f5fd45e874b20b7668ef18e715a0b8efe1fa86943784844d88442b,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\Minuta ao BM.docx,18441,96a2f0c56836193409e960362c8de72a28f266e73fac594a37aeb9c81f2baa67,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\licenciamento BM\REQUERIMENTO.docx,22496,e79179abbc20030dcbc6ee91bfdd74a7265419b2b5a473521b3ed2ae60674904,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan0001.pdf,140871,3c1143fd565d92403e0c175adfbea293afc3f187fd6a201ba26e1d45a998d2ca,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan0002.pdf,88860,b6a0ccac07eef71294089dde653f6ed3e600196b75836d69c0e99687e199d6cc,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Consulta\scan.pdf,174964,732ff341bbd4c0c05e8accdb6919fa6151d18e50e0c3ed0cd618a4fd69b9018f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\exploracao\scan0003.pdf,144995,f1f5778426d16fad122f1df32f40df1b2cd66f5c56ca41a9ea56499f10ed8d60,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\exploracao\scan0004.pdf,150054,54ee525982c78450611a3c4b93f77ecc00493decdba4cf982bbc45e52de1cf01,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Formulario\scan0006.pdf,243123,a45ca527e0581b95939f0a35bf107bf78f24e183513e5ce4ad81c0fe6fec3e53,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Scan\Terras\Formulario\scan0005.pdf,286614,d994a036effb269a1bf808164518fc251458379cc15f1a4d5730e8bd746a9a37,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Uma empresa cuja atividade seja prestação de serviços de consultoria financeira.docx,29727,cf47dfd9686b1d9d8b13288d9b08f720d383cf69abe98f3dacc859c671b3e839,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatório de avaliação e melhoria dos sites da Tempo.docx,38778,ab8a7dc7fbc84bb6f3986b02f9d7cae687708fd501803bf468bc614e1d6ea48d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Checklist para consultoria financeira.docx,34071,55d26f16a8da9cee38a5af23c4c4a3f8093d22da096a6d395e3303c218d893cc,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Revisão de Arquitectura, Dados, Segurança, QA e Produto.docx",20577,b30968b1ea37c14bdd6b4d069aaca66dd82cb8e38d2c3575923b23a23b5430a9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Excelente iniciativa.docx,68066,4583386335ddabd88ad9c2910aa30990a4794d90002ea36cca587255d4a9282f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal do investidor nova versao.docx,799591,3f5040c038fb57702e6cdfad31318730013f9831dd1def99a63df2a084354333,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal do investidor nova versao.docx#word/media/image1.png,708019,753b54d3bef8f345127bcfb3c5272a96c89a03b65436bfaff86cfd22b887a7b5,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1d.pdf,245701,80ff061f26ece6906cc61bb6f0e738d437a6e8524511b80c0f597a919041b0d7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1e.pdf,215107,cd61f18a374a4d1124bc4a422396f77067f0b92ae18ac35ed3ff1bddcc6ae321,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1 6.pdf,239566,d7f27e01dc9b7369ed60de804ddb7b8c1b33011c00214f58d92742a2648937cb,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1f.pdf,253712,cb6dd9134ab2c1708bc7f746a5c8e4969ce7c2bf750b326cfb06449a21361914,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1 3.pdf,253712,7d4337a3eb78f71aeec818d9d5e0fc3c35aba5b16cbdd35fff2d731918eaab43,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1b.pdf,249702,c8b5505759bfb1beb28110cf0506903776e0da032e5f2cc5f69b32b23586488a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1c.pdf,259985,f43ddc80836b8739c406b4e869ebe103732a7f1e37d6a44bc7657619f0959b45,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1a.pdf,273681,9b6abd4b188d8301e6d0edda8c9b576c4d6f058bafbe7be6e234e9cebda95565,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V1\Protótipo — Portal do Investidor v1.pdf,351770,c198b8b7cb2e1eee5227be0aada5193cc73435848ca1aa0a354752db73526722,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\aereas de investimento.xlsx,36868,92921856c0b89e22187ac4b370438dac6023c55dcf335b58f6e37d9dfd4086c3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.docx,799605,9dee08d0ebbbb262651a01ffc7e0ade97323664bda59fe8ce0b07ead82736ce1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.docx#word/media/image1.png,708019,753b54d3bef8f345127bcfb3c5272a96c89a03b65436bfaff86cfd22b887a7b5,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\DADOS cartográficos.docx,18479,42564bb1d940ca4746317a1c7eb0f81212b8ce5a1fe2a98f993bcdd5835c7130,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor.pdf,239566,55124d6417821f0b0fd2ecf8dac40bc098fe9638cf3a281b338ed3643e6b85e5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Reformulacao do portal do investidor.pdf,530948,6fa7029ac4beba6979ed08b33f5264ad4f05b73139d79692b03feae41cd21105,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Principaispetos da Lei de Investimento Privado.docx,47642,1a11706f2a63153791e85394f361ba2c7e67c671f738570e3e962824bce2a1a6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Principaispetos da Lei de Investimento Privado.docx#word/media/image1.png,358,b09d2b50f5bc910bea7dae0125f4d85712072673f411faddbe983261542a7544,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Progresso do upgrade — 25 de Setembro de 2026.docx,19826,2e0441552afcabf084b6f9044457b3217823105cac748d9062b35f274a9f02ef,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\requisitos portal chatgpt.docx,70761,b83360bc1805480d176f346724e0a28f77b3affcba575e2edd2e08b641352642,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\upgrade do portal de investimentos.docx,1332169,471012abb0f56377956f4ab822fe3186e2561bee0471508a5d807091f2e0154f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\upgrade do portal de investimentos.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Unificação dos Portais.docx,41650,5b8f4e35c77f8376eb55d80e0b05826c2a754d76e285e2a697a98e87f52c482d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\sites da tempo\Avaliação geral da página www.docx,48183,1a5e2ca2554b59c5ad484c6f2ddc5dd96a905d6a91fa37ebae1fcd92a7793828,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\conteudo local.docx,28720,5f8b2bff0ca00f2cd85b6fceb1972dc22fdb4a2624e51dff1b26d958f642494d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Progresso do mercado de negócios.docx,18811,e6fb8b747ae21bdb741b620e48c4c3744a01dfc19bdb3e43bbc7ce7ed458ee89,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor (Informação Pública) movel.pdf,367810,f321f8490cd25792ca034b32b5c9ee197c59c703bda0afc04cbe8cf65c57bf58,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Vamos criar uma versão do portal do investidor onde.docx,22443,1343b30014a2fa4bcf428d65b02d3985ba56c7ed477d7380348f8920b1cad6b5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2h.pdf,258241,e712b549b7dce6fb9b3f23148e4bbbe7400900740139d0b14c871d434a06b6b5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2i.pdf,220076,6f3bd3664394b85cc4d5d4bbd9bb17a78ec462af65d9a9e7ab6e945b2cf3bd4d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2k.pdf,214882,a5672e4078ff74b26307dd35488e16427c50bbadac99be31ad360377c9d55eff,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2j.pdf,209176,1554440ab74ab98810c550b25370291e4d0c3c8eabf43a940acb2382a9da51ed,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2m.pdf,235400,3307b93b078ffb270482bb8eb2365f71acd023d53204dc8f3dfaeff93087dff1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2l.pdf,219233,257fc4e938899a47da0090a96d2f5b401afe3e5ff981acc5d9f6d8ed5c4dbb7b,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2a.pdf,418445,f10d866eac013a917eee7890117e30c687bbf402202ffa9a12732c2b92514b92,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2b.pdf,270399,699f05745e6413132e4f0092cc903f702be31651bdf6436fa71d16a75e09b03a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2c.pdf,291689,590c366991383f36ba11c99da810aa07f84d50d257d3402332fb0fe1ab72b5f0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2g.pdf,247322,aa524c56eb1940c14575d8352497ed256a0aed24732eea2d3358a264d12cd2b8,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2f.pdf,245144,53cb235137563ddb1cfbb0d7366f61d4c4844521f4d325eb40ebe8f68d24d3ae,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2d.pdf,263586,a995e7c92e6a7bf19f04e7892e37d1771df2b810876f976b7d4c1cf5c56884a5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal v2\Protótipo — Portal do Investidor (Informação Pública) v2e.pdf,222937,2c137bde9bf606887e395ead7c26fdf639af94a12865d556eb1a3767a2602375,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\projectos.docx,62841,f37afdbfd773befc742146f053de765a1682ea93123aa614947c1180f64d2013,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\integrar o SuiteCRM .docx,24325,79b04d446619f6dc9a3bd5e533ee4778bda196b9dff6bc228b365ba0e6c87279,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Matriz detalhada de oportunidades por sector.docx,30331,73d7f7792631d144d69616061354b88fcbbedce825d0af533d5317ed34c8ccd6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Portal de investimentos v4.docx,1662261,a0438b98c56ce930453f3eb519a952b3274c01fc421b2a2b4c5a994e988a84bb,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\Portal de investimentos v4.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~$mulador fiscal.docx,162,e0180ad0d9fc11f260e4f3c5f49fc648f55aa18e9ef100925cc054414bfdefaf,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v6 programacao.docx,1658773,e1169a7743b13ff6c950d3ffd4672a2afea32e81da84885e11154b7d8de9241e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v6 programacao.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos -casos .docx,48412,b44ec86d313eee6790be68a829f43e00c21e191c16cb89b4f8c37dbddc26d0ba,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\correcções a introduzir no portal.docx,21538,bfb24adfdc43afac8492b30b6bb2b7c57d5a3d57c7cd36008d9fdd5a80cd7dc5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\cartografia_moz.xlsx,841177,2c5728c46973866371139cb080b1b1837bb980a43ae91693f0b58f2263a6c455,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\simulador fiscal.docx,70093,55997917b3bd85727cffac880b6c46fc85a78fef6a005798b9a110a0bca60fd0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v1.docx,1338438,f70ce3075523c6278e00dce15b9c7acf2b690679e16959ae5f7d007e754cfc6e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v1.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v2.docx,1417663,51b8f0ad3296d1064a5c12b450874fc72640869f10a164319cd7f3153dd3a086,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v2.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~$grade do portal de investimentos v4 programacao.docx,162,096add1ae344654e4bcfaf80cf0578da35022211d0937a11d4288b809cec2f4e,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v5 programacao.docx,1627296,edece80c0519537244f8a8b86456af0aa92de1c526f791bb0ee9b85af7a7e8b2,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\upgrade do portal de investimentos v5 programacao.docx#word/media/image1.png,1137172,06b3fd98532ee4ed1d80ce3f1198fc794582577982cec1e173bbb41a81906452,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\simulador fiscal v1.docx,142685,f038d338fa0247ddd70f9dd34e72b080f9b7c93acfc02aec0d433bca1ee606d2,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Portal V4\~WRL0388.tmp,81042,2bdddd284d9c728eb4c1d93a90dda11eda1d74640091b54ed14e0577c0d5ff4a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\IA propostas.docx,38021,2ca6ea33195ae3715ec6823980b720ea011ade6716a9885ee32d69f808f0d529,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\codigo .docx,53404,d3b5424c916ca3a727992cfeb33cb9f03c7ad54d2bd6a4156c11f94bf048223c,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor 1.docx,388939,efd550fd2a9d2a21785d7b3c140d4608f1ba27c52f156e2709e9fbf388a1a569,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor v2.docx,403675,9f5719c8b0cf78855f727d980b77a8f9409fc7f93e303e25d355d009a07d5734,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\backup\Reformulacao do portal do investidor v3.docx,132293,626cae3d584658842ca36b658e7b5b3cc98d87036747e65b29274f0209734e5a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\instalaçao investemoz.docx,15796,c74196f927250a35778ab5896e17567aa9689038b99850ab09659b9b7f2aa89e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx,5456742,bcbf8ec976100cc5e978aef54050c3e3e9d959b0d361fa80a788528a8e5049a6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image7.jpeg,545244,d98834afbd035360b025571e38d583b0ed5458afe7f88f0f646badeecbbc40f1,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image1.png,2824071,bc81f42453ded18fb3836b665779ac9100d0f3c70d5b6a2505cc5240fad4b2d7,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image2.jpeg,468173,c948779500880f5b541a49d96a64c7995e8a41fe5fed9d4514c609b3cceb0ffa,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image3.png,91096,e4e3b71dd820cc3733ca0e7bed74be22418122affe1a1471d62a10a6ecb5ee17,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image4.svg,6746,d5cd72d2a0f875881c47f2b48945ea54da1a284256da3c1e17d788946eabc3c6,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image5.jpeg,678237,3358f74fd99dcd54449349a37e3bbc8010acc4904b6cfc516a9e7228b54590c0,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\MPD_Relatório Final do PII 26-30_2111.docx#word/media/image6.jpeg,538480,efc4716c0764b2adecc020d7c650e6f7725f8ddd2c670f3f471b6c9f50063a84,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx,156864,b1173162e6cd0c4b5bc41dc224685cf0e50f1de36cd70f7bb1bc7a7dcc873f4f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx#word/media/image1.png,44266,4becafb4b86fbdcf74bb8f79272e3ba79be99435ca9e853c6a398cfb836b2d3c,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Pratica-Portal-do-Investidor.docx#word/media/image2.png,66716,ccc2bca23bf03dc49354f08dcf9ee341568ef08e3b106682fd7ef1ded5a77b04,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Protótipo — Portal do Investidor (Informação Pública).pdf,417543,c5d574c59fc0587ba8889125f775c88b690834d91125518e959b273a1cd4ce66,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\portal do investidor\Auditoria de cobertura dos requisitos — 25092026.docx,27257,071345e1cbca77810b96beece4d44e12c57242cf6cf99a6349ddce45affb9207,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\sectores.xlsx,10689,8e263ad5a450903e856ca0a2ca10770951638cf1b90dee59a31bf0c5e567357f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx,2392539,0c91bfa7a2ca1af99f8957597d6225c4e56567cea723ca8004e6661c4bd79513,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx#word/media/image1.png,1036841,c189c22ba98ec837d9b8e934a904666b316371baa62132b59d6e49ac72a5f334,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Proposta de Arquitectura Integrada e Partilha de Dados do Ecossistema Digital da Tempo.docx#word/media/image2.png,1233132,ac02380189d8ecc388625eeb3737043c722fb35ae4128d3a7fb8508a39c3f466,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\recomendaçoes do CRM.docx,21697,427cd1df6fccd888e24e8c2dbfa81e2db86a4132fc24d7a618e09ed0f399e220,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Benchmark_InvesteMoz_revisto.docx,54060,7fffb2a6ba01ce605504896f65bb078e5f9f906fa399942ca9f4779889809617,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Vendas\vendas da Tempo.docx,62880,52c613bc4301d388d6cdedf90af5074ce2ef0e7d06a7166f25fb352cddd0e55a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt ZEE ZFI catalogo de invest.docx,81500,dbd59fd85026e8d2cd89a4666e2385191fc1cba376bb45b7425064c6deac8395,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt ZEE ZFI catalogo de invest.docx,162,6d45cebdd4fb18b8ed43e6b54454804425810ad3b21312165aae25628795aa61,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Fases de implementação e respectivos prompts.docx,20742,bf0a33961c3b0f68f057584fdd6c2b62266f617ad8a3cdff297e7294138b025d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt tabelas ZFI ZEE.docx,34492,22010ee3d77d91474912890640fb74c42f81bf20fe7ef416ee54a9018142e4cd,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Método para executar as recomendações do relatório e corrigir as lacunas.docx,29103,d57343711b38352901526e18945a6102f8aeabf377ebdc4eb135e89b5dac1783,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Prompt a serem aplicados .docx,17943,757551ae205520aa61c688a922a88e2004b7b70bc44db31d08d1d11b5ff7a24e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Iniciar uma revisão funcional transversal do portal.docx,18499,99a85c7b7fbab720f958eadc5cc49c61a07c49eb1e45cd79c4b8492193710230,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Detalhar a arquitetura de integração do CRM com a IA.docx,19823,15415735923b3753e499d8789310dfcc6fa0222191f826cba002ec2d239e1a01,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Definir os campos obrigatórios das imagens.docx,20689,5c126b3551be81c27a8b8297cf20aea5f62868d0177e5312b37e6d04b0adbb28,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Optimização do Catálogo de Investimentos do Portal InvestMoz.docx,19378,46f95f4ed8271fdd7aaa088bf861eb4617f16051f569980e76bccf5cbbfb3c6c,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\perguntas para o empreendedor ou investidor.docx,23887,27d06a797640e6cc5e1dae45ffc84822081cecc32565fc9c9a2a5bc9fd273458,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx,423661,d82b35417f3bb4436cc33bd96cc367a3592d88d9ac0e74d413d502ee0a454849,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image1.emf,146356,675a4fd6492451e600d249ef1602349ea1926f2912f30a243e9494da1a03971a,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image2.emf,118956,3130897bd1fb72233d1bec77d3da86fa92af2bc1440b2059b5b7183f6d23a2d8,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image3.emf,30908,c4c51dde4088e49b62e22cab8a8f6c9c9bf7c615c0315c6da1d90b1e89a9a1bb,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image4.emf,874048,cef9c9cbc48336475524dd2a044f80482ed62a7422e03568f61ec4b7a33b3ccf,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image5.emf,255104,1dc259f7113bd5ff47af5cf4efffcdfb8e719973df714f3e31114e5a5380526c,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image6.emf,170372,8f4fe8e4c6cbc331bacf91595533cfb87b0edbdf05ae268a2ed9c7edaead1f21,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image7.emf,136852,2fd409005f2e33ca011be5d9ff7aa460c0c54c5f40a2b9093561b7306ae49a2f,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image8.emf,216420,247da53a98e039cdcc2eece983bd2c4f1c283990fd641fefe3c5ec738997ff76,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image9.emf,99936,fbfebba12507d917e4e57a1f7e29e71a7bafe0cc69ac20c2da6de967ede2087b,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image10.emf,213556,8841a3576a2f4a62dafe0d5aa495d215386372ae1c4c82cfe5b0968841a90edb,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image11.emf,84940,7cbd43169ab16ef7ef00f85a50b8da774660753305870c8dd807d848ab8c1f56,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Plano de negocios\Plano de Negocios template.docx#word/media/image12.emf,271360,4c918c38f44d7af0ff07945f1a4f0137b0d56016a47f43a67fdeede8b3cea53f,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Formulário de registo de ZEE e ZFI na InvestMoz.docx,25178,9de3ad1a27c040365d3f688ed178cc0994cfa29014c65ec28589b2e76e4068b4,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Recomendo que o Simulador Fiscal do InvestMoz.docx,148831,faf42f9b69c64291f1ec9be268e912bbe964fad9651e30f3467b6384e4ef5258,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario para publicar uma oportunidade.docx,23372,cb1a117ad5e33e1117c4601ecbb43a7b51c1248df654f0c157b4fa593b55fdb9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\~$rmulario investidor etapa 9.docx,162,5cce0235d6093310a048fea6e95053b544a46485c9408658e679729d282346f4,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Melhorar o simulador da investeMoz para utilização pública e empresarial.docx,25831,f3116bf51b04216f9f524f5d024288c9a2c04ba0c79a284b86a808c6808940a8,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\novos formularios\Especificação do Formulário de Cadastro de Oportunidades de Investimento — InvestMoz.docx,320004,9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Formulário de registo de clusters na InvestMoz.docx,22723,e1a546e7e2d6996b7f92730e6c1421dd6faaef64a45970a30dd5770f91035e4f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Requisito Consolidado do InvestMoz.docx,20847,44295a85c3ffb8568ae4c496167fd5d79381d44b0724f4e11ba6e471cf4e1ab9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario investidor.docx,55430,380df6e0c7236ef208df93b4a1db033db71c04033ee131c7ab98668adf677f17,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Restauro do portal.docx,44491,12a297f80796c6fd753bc385117016a8f86940312fbf380d52ac25bc403e2210,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\oportunidades de negocio reformulaçao.docx,22890,11bded2839398f8de4f10d1f653200979eb29b32735417f2e380d92d6109e3a5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\formulario investidor etapa 9.docx,55432,154f96a543febd6b9be51dd26025048d13e7e0efdf51ce88770d2b561891fc13,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Formularios\Zonas Económicas Especiais e Zonas Francas Industriais de Moçambique.docx,22246,41093a37ed1265870a3f4e0674ac7218ac4b7bcd7047ef8d927b69750b9f4f50,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Prompt de Validação da Actividade Realizada até ao Momento.docx,26196,827a850ccec7616b6033754869042f9a2ccd63b496b60e253918584ef913a52f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Matriz detalhada de oportunidades por sector.docx,30061,9f52c797dff6f7adf1904efd6e15aaa8f552b7443e57269533c39b428c20e9b0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+"C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração de ZEEIntegração de ZEE, ZFI .docx",24398,086b0468934443d48aebe6707843d481faeb323e78b161a2f5af0c2283217773,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\parques industriais e zonas francas.docx,27152,c5a6945239ea9ca5fab18510fe15e33deeffe8fec72d811f5a639c7388fdcab3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementação da CAE na investeMoz.docx,18546,ed71465abc672d84471117f710c5179160815d3a02c1c121bd43c915bdab38eb,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\DUAT.docx,25817,9453ba3bcffab0132a1996aeb26d0048cbbb6a3b52a9d0b6a5f7a44129a553f9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes.docx,444929,b46d377c5e98268110b64851fd9f1705a413bec9ae7a4eeb4c9c0f2d4160801e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes.docx#word/media/image1.jpeg,383819,a23b342fab66e292cdbded2e543dc29c70ea0a2e01cd5c3f0da804a6bb81291a,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\tabelas a implementar educacao.docx,29789,8471f5f41f5113ad779684f6dc0d62099f130ff08a4cfc74265dc25afdf2d693,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes v1.docx,466730,3bddd804585cee55b6d22fb49d551f13da1b4ddaba237bc5d34dcf85eb57814d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt mercados existentes v1.docx#word/media/image1.jpeg,383819,a23b342fab66e292cdbded2e543dc29c70ea0a2e01cd5c3f0da804a6bb81291a,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Base de referência do directório empresarial.docx,18391,7e4f6dd21185ea69560907edd119f318b91ec4f156b693bf945d17954017bec1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\prompt de gestao de educação.docx,52637,94ea9a82cddc6e4e265d630f53a464d69a294e93b237b1ab395c62517bf89040,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Complemento consolidado — Criação de empresas e minutas de contratos sociais.docx,20050,b20c6517784b6d44aa22beb67748d3f3b224f58c60a7dcb378a185669c2c543e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Requisito consolidado — Ciclo de vida da empresa.docx,19453,c027dc23895dc743dee65dbc6ab156177226087c2770f63c16bef56219358d36,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Complemento consolidado compra e venda de empresas.docx,19903,bb216f277efc168910d80f32bafcd7649e53f7c72ce4d1f11cf7f523ac7521c5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt consolidado — Melhoria dos ecrãs do InvestMoz mantendo as tecnologias existentes.docx,26653,ac6c720d00913c38fd1fabc6114b73580efd0045cb9b8ab32126df6eb0eaa8b1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt de Implementação da Cartografia.docx,23758,467f4dffffac685a4c2f9e67c844b3c5b9e8759f6dc593723c73242f4e0f1818,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Perfis provinciais e contexto territorial da investeMoz.docx,18558,4ea5eb0bcb3d77cd2623e4fa47ea39838398e9355e2c94400ed590007f1d53b4,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\prompt obrigatorio.docx,17749,b0845167a4c94cc0852b7dc569bc69ac30b472cfecda8f8416d1f7fd1cf7d672,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\~$OMPT Competências e Oportunidades Educativas.docx,162,8618266de24e02c06c049b850f55b03a965145e664175a6fec70167a73e9b7ac,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Formulário de registo de clusters na InvestMoz.docx,25760,31828090185b73dd8594835dd6f850e312a30b824ec9ce593218d3d0eef30b27,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\PROMPT Competências e Oportunidades Educativas.docx,110812,5da580e3e692a3d9e105c1ad98bfa745acdc5db40dec3491f8baa73f98460198,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx,880118,5159afe652cd598520f22c75aa02a3b1e9a51a78b0a29a1188a66363f720feb3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx#word/media/image1.emf,17864,66b170a85568efaa3286e73ec1cd707ae976f42a5487c7978dba0f910e7228e2,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Implementar o módulo de cartografia.docx#word/embeddings/Microsoft_Excel_Worksheet.xlsx,840317,b4544df3edce037a269055be2215b2045917ed372dcf04948e2ec16f95e4b280,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt — Integrar a lista de países nos formulários do InvestMoz.docx,22105,cf7b024ee6401c710662c6b7c310e30f50791729e9f74bccdbf72bedaeba6ea1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Prompt — Incorporar projectos âncora e investimentos do PII no InvestMoz com rastreabilidade.docx,24323,d63e63a5a03275170c6d3037b6c3c17d986ced9c791fcc2d754ff6e3ad4b7730,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Revisão obrigatória simulador.docx,19879,22b7da3b9135c32f392ae0363f3b659242872f12096e760453dc9cd01f5c1ab7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\oportunidades de negocio reformulaçao.docx,22888,8506a1583541cb8db32df9691d2e994aa3bebf99e2e700631c670c056c03fbf3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração dos parques industriais e ZFI no InvesteMoz.docx,24372,640cedda8dcb21651fb1021baecf00b887276a219c528e8aff04f1397831163b,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Integração das referências de oportunidades de investimento.docx,18441,6803ef863bc63c7b6e4be5398307a7238f057504def841e7d12863f9a437e3b3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\por executar\Modelo de Dados Geográficos.docx,48773,408815d07b9ad63a65daef15cc2a29d58f85fbe56af0d167914c1be0389ca0e1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\cartografia_moz.xlsx,2235715,1e36c769c4767420b10f1ff5ee0c2955cdb1b03c98179c5cad549e832ffb1f15,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt CRM.docx,29822,8a039779c58d036bb8bfb974e4374086c9afae31fde3b0d6b6e6a1379ae680f9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\realatorio de auditoria.docx,22314,6e2876d13d8c06db17aff1f2284eb0f298c558a9000fdf3e738e02beecb1635f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\PROMPT Competências e Oportunidades Educativas 1.docx,36189,183bfb8860d2bcb1af1bc9b897deeb98ba789fe9c7ecc08e1ec63e87d0e25663,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt CRM.docx,162,e815230666b07ca9e6120d2f77bbdcb3b334892f2857b6fc8b825b6a8166d856,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\revisão indica que vários prompts já foram parcialmente implementados.docx,21552,4e4fc9949eb8218dbc01c922efb184d906409c41a8290f4d984b089df00d8aa6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\PROMPT Competências e Oportunidades Educativas.docx,55730,a8b37ee54ac5ebe8f22238bfe46b011a3d385a593601088a0514efc93d72cb69,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt inteligencia arteficial.docx,34436,769761caee9e4c9b4ced1a71d877b40f3de7c6721c9d85bf6a53c05197cf2370,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt dos ecras.docx,42439,ef26857a139de66e25ee43d3a49ab5dc3e6d4b1f2c2eeafcb3579b74261538ae,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Pacoe tecnico.docx,30860,4c50196c21e1add220b423fe5fa70fdc00f65332872566ec49b1c8d3c5925ac1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\~$ompt inteligencia arteficial.docx,162,58af9455e09420443de9805cbf484b94721e299fcb75cb02cd12823fc9cac356,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Restauro do portal.docx,22560,ff6a04b4950f9ec3b079db934a37ee7c7df3811eca46890e77c0e981309dfb63,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt para resolver problemas encontrados 300926.docx,21446,ef75499200824189bd8e2e022403d4d7c8d9a1a0128e28fad7915ebc883b12dc,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\prompt corrigir.docx,21990,dd72b1aa7c43af3dac9d0a447e6b0d2304bbbbaec1f9846f13781c74328d000d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\Prompt master para revisão do potal.docx,30640,a9963f4cc591c7df88630595bf09b616d408062011b663b9f95cb73b231a61c7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Cópia de dbrosemin.xlsx,20076,6ff3f15d4dbedf78306ae3cf5f53bf3648553280fc74f3184c4ba4b9d37e08bd,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\benchmark de melhorias investeMoz.docx,134291,065203aacfae766c62cf9c2c272ebacc61ff23bd4ff9e91535939fede87f7617,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\melhorar e transformar o Portal do Investidor atual.docx,862272,d0c06a759693e7b74c6daec14539e247e2bbbd630bcaff59aa01b2f7e9aa977e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\~$ojecto ancora.docx,162,9424159b007fe38435e4ab829e2f3aee55d514c822278d0d78e265e4db5de9b6,original,"Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html",Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\novos\projecto ancora.docx,54305,7da1e0f49fb106724c2e416c34905d76249fd27514d0aa2066cde7963cdc4c3d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Corrigir a ausência de ZEE.docx,19153,453cffa885086eabacdae7138879c096649b437f9b4c62572f5d35744cb231d7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Plano de Optimização do Balcão Virtual.docx,79900,74a8ce293f1ffa153c7a1950413fc94c372686c28f5fca43cb751ea6a5f94f03,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Bolsas de pareceria Bolsa de Parcerias.docx,86714,0c2641ce634b977c99df8729c43f80e5935d26e2a4ed0cc5290d08938bcf0be0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx,11997280,a3df44b77878970ef68303615f85a4e88e600ecd6917e6c82d5b29f01b8dfa98,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image1.png,1626117,f44dc437cd1c9b6a978f30fb9ae8977f81e30e4177e05eefb5c5a54cb8626336,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image2.png,1745395,e42c3bb28a1bc0c455904c27f9ba0fc18792efb145fd63c107c3a5166874a4cb,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image3.png,1913792,53fd77a360a7ecb6ff67c733b92d66cdcdaee8ef078d8025243d2cd475a11ca6,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image4.png,1394028,b5f458bff34c013ffffc73730c2637addc7115b0bc58c326881d330969001eca,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image5.png,1382473,f0dbbc1025013174f5bedc453d1e8d476456e36f307850ff1bd66765fdeda09a,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image6.png,1313377,ab52dae6a50fb216b8daaea09b72df019ce9e93ec5b0fb1a3ba8f7eb670e4b02,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image7.png,1437364,72afd50f29f2d2c6e322927a56ba04843c1ca1fa7b9797c5dd91047eb6777e9f,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Roteiro de implementacao de ideias.docx#word/media/image8.png,1122339,fc8529eb2af0d89f83003143e0afd039a7e8948ea00aa615762bc669c9d31097,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Estado ZEE e ZFI nao implementado.docx,24370,a1567e498bafeb0665566b26bd0540cad2e5031f79de5727eefce9806a238c7a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\auditoria v1.docx,19610,a58f4c47cf9306a02193d82cb607f8493e47fd6e9186df7c8e41bcc780c69d67,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Benchmark_InvesteMoz_revisto.docx,54060,7fffb2a6ba01ce605504896f65bb078e5f9f906fa399942ca9f4779889809617,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Não há evidência de que isso esteja relacionado com a compra de tokens.docx,21957,f64d930d8a86c11e141b344e37cf294f16273190c2374689a221457a2e3476b7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\DECLARAÇÃO DE COMPROMISSO DE HONRA.pdf,506695,7c9f5af3100b32781018862c4b9e082515ada087a49fdb096feeb804ad8cb466,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\implementar.docx,26053,77c2c84df6b09616dca6392d0c6b78ddab36ab82d7900cea29cae95aaebd495e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Evolução do simulador investeMoz — diagnóstico e progresso.docx,121493,f329a5aed39964f098384ab2e4380bd5f8479bd04551c315984d0c5e535e7aaf,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\SuiteCRM.docx,26455,3dbef3e4fe8cb604be760ac3f556a63bc2643343723921031a2a56ffd3880144,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\Integração dos parques industriais e ZFI no InvesteMoz.docx,24369,a3ab1d84abdd83ca9400d622b0a6c0af65c124f6de043840bc739a630a9a36a1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Conference on inclusive and sustainable development in Mozambique July 8.WP edits. docx.docx,34821,3f80c5affb0e54c53bd04e82cc37846e09be9bd67728483852043d26a02ea6fd,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Conferencia Internacional MPD.webarchive,14929099,f37af58ca54667a1c83499ef33230c14021b9894b2c5842d584c1ad337d6e28f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\~WRL0575.tmp,1305935,6c5aea9972fdeacd045793abc774473a6001e90d8ae4f4811a00f671a5105470,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx,6803032,c7f725f5515074807abdfff6963cce472420277fe352f4cbc54d438ff4260c00,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image1.png,1323697,8223170912d288e7741fcb884c46d83690d98b525f570ed139b332614296b6ac,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image2.png,1407311,6ef4609c17aba403a0d67e9fc166ec8e148908a4f22e3bc5a084487647386859,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image3.png,1729491,69107fc52e1a7d2ed39821d8ee0977958e382b6a09cbae5a5095784b57f968d7,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\novos modulos.docx#word/media/image4.png,1865233,3fcd53fdac090ca59834133089a19fd003150c2fb89adba92a896051bb185855,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx,59538,d3ae0d91ac0bc6d6cc73aabda4916f1c8e2e7450a051126ff39e492e3cca7c2c,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image1.png,980,6b6ad303a6c9b48d0d086a2a9e9d30b2de4aa58da44f59d7d93dd8dd3727ff22,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image2.png,13242,e3e34126023e0f413ae599d188d6fd3c30aaf64933711e4c7ac67b9b3fa4a2ee,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image3.png,414,a46bd049cc2b9375f7dce99347b28cfbff2f484d9987ec9f8d4f7d1d99b0e1f6,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image4.png,12198,dbc05aaad4448c31ca450bc3302493c2be6451b470e897c343dcf2dbe0793b7a,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\legislaçao e localizaçao das ZEE.docx#word/media/image5.png,579,59212bab985967a734c29fdc3d9f8db77347e87df004d579651562ba486140d7,anexo embebido,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\006f3ea6-5bf4-4315-b3b6-5dda9c3a6566\Pasted text.txt,6842,dbf5afdca293302bb84389ac33aa576c25859f8fa54e26d0b9687b9c564be005,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\0ad28475-97cc-4263-b611-022f3de5bebc\Pasted text.txt,72880,f167d9156c2572c0253949a6f0ed88aafc28450cce902e8f445e3d979119aa37,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\11c236f7-e954-499a-b290-3d6dce07543a\Pasted text.txt,5158,a8241744db40871b36d0a2b39796b7168fadcf243e02a352fa794176da389c95,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\13ef8ec2-be07-4b10-93a1-9fe134b928fa\Pasted text.txt,14654,8185bed1e45611af8861c8f00568a7da6901896e2650355c41642805485ffae1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\1b36f6f0-93cf-49aa-9479-986a57bd18f4\Pasted text.txt,37098,470913bea520a8ee267f8df27c0849e12e0632d0ede2d4556ed463c994b82161,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\1dc38f3d-1455-4b18-8358-899a66386a7f\Pasted text.txt,36260,05ef8ec7da01b185ff0872e917e9fa9c5c1e7407c3d547788f9ad53930dd5990,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\22ddc8a3-c393-40ff-9960-dcf7bd9e34f6\Pasted text.txt,8230,5464cdaab509637a44adc08fe621fde45a0bc16c8fc3aa9483fb1b9f0f9e0e85,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\2368cafa-157f-4177-ac75-255563247749\Pasted text.txt,16046,300ede994ba6cbacdf7ffebb4cbd75777eccb3f359842491404357e8a549b235,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\23b033e6-9ee3-4a6c-a41b-688fe7f09795\Pasted text.txt,44742,5dbf82c2d8ba2c9056b838c4565cb0db9de28da4173075bfdc12b233b3c43fe9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\27922f5b-f041-47db-bbf1-6bc50f3a83dc\Pasted text.txt,37098,470913bea520a8ee267f8df27c0849e12e0632d0ede2d4556ed463c994b82161,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\2daec0e8-1c8a-4606-bb4a-b7fccd0ea7bf\Pasted text.txt,0,e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\2fabbcdf-a098-4a0c-907f-b5cc428c4608\Pasted text.txt,12095,991d4b34e6dadd23f4c66a61de509fbac1abe83d8cbb316dd24ba400c6f13451,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\4b4f7002-adf3-4004-abb0-f389778dc08b\Pasted text.txt,5601,02f44bafea4ba47adc8b24284d4b189ab9f1db3f6c1d1d63fc06178c400f9ee0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\50aa6a01-de6b-4fff-9625-46dbbebd033c\Pasted text.txt,13287,129df97b64e3747d626b89e25f70bba14ad50ccdb47f08eeededd41d0509ebe0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\5d9b9f23-04ef-4e14-89d5-bbe6abb4a06b\Pasted text.txt,24256,b3e17bb11d6ebafa121b623c8ff8949812b35ef0ca5926a33c22f3e2093a01d9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\5dbe0293-16ad-4975-8956-ea48778d6510\Pasted text.txt,23804,6e51cfcd4ee1329c51736e0fb1a47668a8e9550de94ead8ffc222ba22498179b,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\602a2b85-7e0d-49a3-b048-de31d42fafc9\Pasted text.txt,11118,07bc673aa256f0ccc73138f70121077e948650683b2dd24f2ead3dd75c76831b,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\62a3324a-541d-414e-8fa8-8cc25c41ded3\Pasted text.txt,8048,7ee3460c0fc278057ffb283ab33d556f58ed8d9834f420c76103f69a0e18fbe3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\65a3763e-afd7-4ba0-b650-1f4c37f3cfbb\Pasted text.txt,11460,dff87ad6bc8d49d487641e0dd577314bf78f75c3d0220a8802461c5da0c48c7f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\7235d6fa-a6a3-453f-a97c-b6741c083d10\Pasted text.txt,16673,2626df4ca70d52cb5f90247af7b6eebbb251fc64b4915ee0ed1fbbb693cb3586,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\77627963-3e1c-4d41-add5-18eedbf62b01\Pasted text.txt,16486,62719366d33c647930cc4bc92a07d8e933c4f0e0dc06d91e2464da86ca4b6f8a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\777f05aa-700e-4dd6-8dfe-e277214fb713\Pasted text.txt,21531,4a12de1c0822ef8583ca5bc7f3d4ffa8dbba1c44fbfbf4e0aadc345efa696f65,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\7cb98fa0-99e1-4dcc-a3f1-30cfa71ea9ce\Pasted text.txt,13591,09933d0e63883e691a573ef23b7c13fa8fcf66556fe38618e222275f5e327c54,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\7f29e161-75bb-4e3d-b49b-cc885c8a386b\Pasted text.txt,5586,cb34088522c04f92f121981407e3376a2c2e3f489d09272cb1dc2828f8c26603,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\8528a9d2-b934-4bb3-a132-a18b7e13414d\Pasted text.txt,30136,6c2ae3e9b43133940dd90fa2be0d24c07eed06ace5799cea3efc25574c0a0e8e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\8865429e-0156-4167-b465-3595b0fda05f\Pasted text.txt,5262310,b2b4878730a3285d9fcacff5236a15671802c172ff28c10704459aa2cfdfb9eb,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\890e42e3-ce0c-4cd0-903d-d97785be9ce5\Pasted text.txt,68522,d60559844425f03f4a722dff3974be91e8e4e279179bd58663ae164fcc9a68cc,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\8a8b785e-862f-41bb-8d03-06fc6f1b853e\Pasted text.txt,39222,0755f56ae929fd37451d7dd589bed8e1f35c6655f2d674ec1be788b2582cf31d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\8b304349-5505-4827-9c70-f35cd2514513\Pasted text.txt,29220,1f0a4cdeefb86d36719282d409205f49a0b6d9770ee1beb32ca82284135a0993,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\95cf3a5e-fdbf-4005-a877-57d4ac1f93c5\Pasted text.txt,11261,a2434658ad9e75e59f897cb57c4c2934b8a28f879e32584f3d00064900c6a5ee,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\9e57f88e-82d7-45a9-b1b3-4ae8cec7f713\Pasted text.txt,11805,f15768c79a22c039b9137b937da003dd61912cd9e8bb9fd7a40c795dd0af067e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\a1795b4c-c360-4e31-8eef-2daeb930721c\Pasted text.txt,23694,24f36a01c9b6d0894155cbf09c17f128904626935461897bf59ce2b811d08d9d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\a2b1c919-0d1e-443b-bb5e-8917c877899d\Pasted text.txt,54479,06996499b4b5a6b84aba61d43bcebbe9bc7d710700bf279172dd92f1016c8bc6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\a57fcca7-d9b3-45e9-96ab-575b1c5a3536\Pasted text.txt,30350,8e6deaa7f0d738299b1ae3b8bf89b633641e0cc0cb5e7211461601c0c2b6d635,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\a89743e5-3439-4543-9382-2df32e6ceaa9\Pasted text.txt,6636,574657f7fc612bf7760a31f200978b289a911df39964b8c60e3b357845d8bd4d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\aa68e897-14b6-4504-ad05-93c2e3f0b4fc\Pasted text.txt,9536,b207d14e53cf13e621a01d0e2bf4bb82bdb65ad0ba07c457b42923299d0336a9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\acb359eb-1a65-486b-8680-c6abeacccef3\Pasted text.txt,14837,99e36a08038f2540114ad87c32423ce9f0aa6c7c7ac866372273b4fd33df3765,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\b1cdf53f-6026-4724-ba91-fb21b176eddb\Pasted text.txt,7348,e115415527ba9a245fd8d44f4b815054f2f22c72152b5d4ba538488a06d14e85,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\b86ad3e6-37f4-4f04-9bbf-6dc33f69250e\Pasted text.txt,6991,a2ad18c729f00e37db23c1b26615dcee50960e0eed7346d6cc013e6a57c2c24d,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\b93f36c6-ac2c-45f4-995d-577c09b3862e\Pasted text.txt,10274,9f6dd1d9c0ca8628443edc69a6151ba49f96a8e044ac8aface249c4957dafb86,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\bf1d310a-d3a8-48fc-953f-0648622a6c85\Pasted text.txt,81460,fd7878021ae5d18c9d4a9a79073552c36876d59726b8fb2612752f2594080ca0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\bfb8dbf2-ecff-45be-8612-c1868ebe8343\Pasted text.txt,6665,cc874c1e0d7ab1d7779df1664c524ae5f876ef7af99b7fec2358c4be7d0e53c6,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\c1ac842e-1b98-4f18-82bf-5155dbddf288\Pasted text.txt,11603,bd55cac92926fd804e358921924740eb9c7e649af7a845fe85d2c3686ae2ef09,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\c6245408-7052-4478-8804-377b282e8203\Pasted text.txt,30976,600240dd64b59b82bdb92e471b475f9efc96eab67f9cd532a432e1e7a324f0c9,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\ce3b9157-6463-4c3f-af50-6d53cba78a23\Pasted text.txt,30586,6381a59fbe8bd8ee5a76d8755ceb320ef2d14fc1e628b8e1cbef2c5eb83e30c8,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\ce71e769-044b-4eaa-9f8a-793e52cd644d\Pasted text.txt,6128,0a64d4fe9dc2d80211568d74cc49335472d7a2be01a199223bf4b1a0fb58e983,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\cfe4012e-cb54-4a42-8fcf-9567bea45d7d\Pasted text.txt,34983,8ab2b0df6b41a483d72aa852984c627a1c41dea3f05e0f13ac3ee0ad6d680b65,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\d53670c4-f46a-4d49-b188-770b86bdda19\Pasted text.txt,8127,c71ec7adb5af079fc5c93536107fe30ffc0906700b5ee5eef6bd2cca1665dfde,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\d5886992-638e-479f-bc30-e327bd7a10ee\Pasted text.txt,12246,f0da2b58af2e30cc1b1cc353f3a6b00a592c800e17b8d00bd2c13dcbf16c5a78,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\dd19a693-8805-4f81-a65c-bf2af031a37a\Pasted text.txt,9346,2453530cc98ffd9b270eef47786a9d596701e4831e2a3c16c3765152cc916494,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\ddd6740c-486e-4ebf-a11e-c9687206178a\Pasted text.txt,7103,149673c0e35573716086d72f65e1b8e6c805c4f890b44722b839d4ce7e6caf15,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\e11a00e4-8fcc-4ad8-8861-2fc0244c4324\Pasted text.txt,23406,c32107c1735d544d91c1c5e6f94c731e71871c66ff6ddcbecedc4c86fd1630c7,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\e1fa9a32-14ae-46f3-ac02-c7115c832175\Pasted text.txt,8246,55050f60a15d18b119c83799231a0af34b00738f7ae8202a232a07df23f65fd1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\e51bbb68-0db4-41ba-84b3-e20754ba0d33\Pasted text.txt,37962,214044c4a4a71430ab8f271ba85256e48c6a08785da0e48ecb7507a04f23b6d1,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\e642d815-f449-495f-bd61-4b3e247e23de\Pasted text.txt,9502,5dff89adce75a8b9e0a699bd31986a1a18fd3f25de7218da2800631365b4986e,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\f003a1f1-4ca9-4193-9790-0ba7c1db9812\Pasted text.txt,5158,a8241744db40871b36d0a2b39796b7168fadcf243e02a352fa794176da389c95,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\Users\macbook\.codex\attachments\pasted-text-attachments.json,129812,6bbdddc9c69558cb97444d77b90be34a20324174289a4d7f3f337de89b8f7f85,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\portal-documents\58abf343-e1f5-446d-a9cb-3255f376ece9,9456358,11f0cab15eb6e51010952203ffa24fdc533a24fd642e19525fe4f46b17a1f5e5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\portal-documents\5c860c48-e8cb-4d8d-ab9b-2e3ea7036ce2,1834284,ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\portal-documents\64c46765-96b9-4f43-afc6-f5b730c010c4,440018,ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\portal-documents\b0ea969a-30ec-477b-8b8b-b7af82a11bfe,67067,5c69b6f189a1d3f5307e0cf7dd8224554705158a682637d3105afad615db26e2,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\geo-ine-source-20260928\layout.txt,57191,2fb8ebe44bb0f9e22e382436890a26822592e1da023b56ca392e9aafdde7d85a,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\geo-ine-source-20260928\original.pdf,67067,5c69b6f189a1d3f5307e0cf7dd8224554705158a682637d3105afad615db26e2,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\0ddc290f-423e-42d3-9d71-4d0613f7a0b7,256,44cffa4321c00556030f25ebc0806b9dbeb917cb3ceb2a8c0cb87be575752803,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\1c466353-ffdc-42a7-80ac-71f4d27551c5,256,212ef2dc1db7df9904d6eafd0b75dcb2e15aa32cfe875c6a4aaa90f3326fb4ac,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\1d2c520a-6320-4a36-b3c5-86afe674947b,256,bce07a2025490b0397f40f1fda70bf68a2a3079c126451c461f23c2a41632f4f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\4e278690-f201-4539-99b3-df9fc22eabe1,1620,091c234abcd17e096dc43df4b58303c6943c9de1f20d53aecf64d42ede08b30f,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\6bff5c6c-aec4-4901-a283-598d430bbc6c,1620,f43cf75b9137934e04ed43222a035cf84dc1d4e80740867a480c194ddf5b2beb,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\88b4b91c-dfe2-42ca-b96a-8b355661dcf0,256,3d8251075f3f377f30c6c76fdea3c7c283a26e35b47f8fa91768860087ae6799,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\8b6201dd-52be-4820-a2e8-1a0de7de6ff4,256,c81fd76282c9cbcff1118465c0725f2e8e7fe173933b52a37a0082b1a82cbbd3,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\91fb5959-e621-42e4-8d31-5871ef95b9c4,1620,d0a97bc7153146bb2cf1478d99b786536f71244e51fd04ca702e1066703ebbb0,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\9adbea9a-f909-4236-9e44-716329274bb9,1620,d70992539778fa94bba1322b6fed0ba59d5dca89c30d4b2aae2e149b0c0b0c08,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\opportunity-resources\a8a7c442-dc9f-4aa1-8f59-9665c057cd9b,1620,abaf5c018b6a9cbaf4a60e181a9da3b96e8b69036a4f88b0908267a3126c07b5,original,,Acervo inventariado; consulta/publicação individual não inferida,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\api.md,4801,3b7e69dd386de8e8b7f0f201aa6257adb383febe5ccd309362de2e2f95b132dc,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\architecture.md,6392,7d1b66c88903f546c7a2f6f18e00b045417c103481d7dd22cd9c7c6e0f89b221,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\benchmark-results.json,2160,ca1f37224f869a91a8ce0ce23dd8f276382b20feb52cdb5bcfcffc4d7a646ba3,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\coverage.md,6502,b3a1e96463dd9926e439e69fdbc313b9417aa1f112da37e82d983511b22fca32,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\models.md,4247,05b1ff348f98f572fd31ea9a5123517948643457e4bbd9511192f32a203cb8ab,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\README.md,4604,4323bb06506ee427a51475c90f7647bd336df667d07b1a44c50640a90db2850a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\ai\vector-proposal.sql,1027,3cf9134615be3cd62b7294c1ee7d8add8800975246a50c61033406af93e76bba,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\architecture-and-migrations.md,622246,488ed8672518b42619edfabb9ca7264e6ff330922bb1b824f0ee4a53dbf690ba,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\architecture-data-security-qa-product-review.md,9884,a2ffe042d64de6e47569c59034bda3786e0ed643a7d242563ed260d19bc44a88,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\associations.csv,2036,aef72b1a2f40576feb1f3cd9df382cd82729ef2569505b297e658d560ae96730,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\business-marketplace-progress-2026-09-30.md,5591,f81f76878dee180eda0d8c3cc908cfb284d22b4c1a471b98048fc0235d3dd7af,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\business-marketplace-schema-integration.md,7560,c9020d6efbe7e1c370798da76d1443ab82e98780262b6ce76394f857582a96b1,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\catalogue-review-2026-10-04.md,13200,3fd361cd1cfc8602529874e80df1c34a5b379ba75b0e1ae55dfe4a474cc63136,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\catalogues\openapi.json,11492,2e91ef5d2a1f2171e9f667d916a077e96f26020b59e592a6c26a8333e05408ac,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\checksums.sha256,5228,085c898a1ed900a5d269e5b2d5b0af2a56ada1d18e2401ef990b93d185a5e950,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\completion-audit-2026-10-04.md,14311,e6ce69bfe5ba9840a4f1d4cafda7f42aee4e69875f0e8d75d9fb017817f8ade7,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\consolidated-review-matrix-2026-10-03.md,128154,047bd4716165360af65c874766297b7146c9edfe5d97dbe5a4299faaebc42cfb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\constraints.csv,39081,61b10edeb087f6a021d3c1d54f45d7f1208ec92dfeb365086a18b10d3a8f77f5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\data-dictionary.csv,184351,94ccf2d0a5361309634356a3f53dd79c23d9abc5b65928a0b3aaca6228069acf,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\decisions.md,4196,6377ed87016a505cf37bf9a69205321ea6c8cd9d6a32214f12225c5850b133b7,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\delivery-gaps.md,8606,dbddcdbd8f1941ddc8502a29bfa433977eefdf3433ca5452643689e50287ff67,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\deployment.md,6603,389cef96440adb07a0085fd1ce386651378f9dcf42911fc1222d4fbab9665665,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-corpus-inventory-2026-10-06.csv,36993,5a012645c6633cdce844f34a4f67ca0ac3c3c7074884236b554a86a2cfb0a908,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-corpus-reconciliation-2026-10-06.md,20640,71c7ef081e4ed20e8fcf31d72b1ec777d8054af283a8636c25ef20c803ee9ce5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-import-manifest.example.json,823,7257e582d70a58dcb993536583da954049d7186f9b4b4ebbbc02bbfa5e9cf5c0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-browser-2026-10-05.json,1018,32a6a0fd1147c98d77bb8864e378e2bb95a95b74664b7b06cd1206ce80021ff1,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-2026-10-06.md,11706,a0e41142c688c7d33578e4f43e213112351d56389f4d1aacc4511eb4e48773d4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-browser-2026-10-06.json,1873,45f0595624860c804929b10ed46f04fdaa4c811bf4c144ae60d88b9280e8e0ca,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-desktop-2026-10-06.png,104742,cd4cce9587832916b9cc48fe0e417307eaf9264bb0cdfee1702cc9852a27a4a5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-completion-mobile-2026-10-06.png,98371,991ebcd793ecc567ebc263896cfd6b6409317e7929f2a88a9deb54ec08b2e403,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-desktop-2026-10-05.png,99244,a6bf38faee150217fd01e9224d6fa3ab0bb9c77b30ed2e72d6dbb06e64dda4eb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-implementation-2026-10-05.md,7296,af56b14093af5faa0fecd85d1221e324602113d838619bde7696942f8bf7f330,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-inventory-2026-10-05.md,7232,8a8eb56d1fb87bb86029698579b4bfe1b4385d9dfc85ffa775c82d489a47d1b6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-migration-desktop-2026-10-06.png,99244,a6bf38faee150217fd01e9224d6fa3ab0bb9c77b30ed2e72d6dbb06e64dda4eb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-migration-mobile-2026-10-06.png,95291,5ad43f381b171ee443e866c1eb1a8f878d9895a3f02a47dc3c237c6a8294b4a9,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-mobile-2026-10-05.png,95291,5ad43f381b171ee443e866c1eb1a8f878d9895a3f02a47dc3c237c6a8294b4a9,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-library-schema-incident-2026-10-05.md,4638,e10f266a46a5af3e092761d4b0784ace0ef6da2dd0249c09f2254c598112f357,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\document-requirement-associations-2026-10-06.md,15749,60e8f9fcfe3b14042cbbee3cf1c72deeadf8f30ef3bc77b78b964557dc98ba7c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\conformity.csv,8588,81e6f0451dd5d5f526c8b7c9a78f61f6293ceb5eec55d4b5ccccde40daffe7b6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\decisions.md,8747,ae144e7594d0e730dc62e0a4754072c09095f4187df8de9e5d585872402f3b1c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\entities.csv,22778,ad66733605c17455a2c03f007ecd1f9f26ec71685d60ee73be959bfb53b8b958,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\examples\gap-calculator.mjs,1523,70dd4a73ba2b5644e66b307279141bfe6a31cd9c991bdab8a4568a8507787d95,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\examples\gap-calculator.test.mjs,2509,eff94de4752e056babe877a008edb0007b123fc5bc87019dd78b0699081a7293,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\examples\package.test.mjs,4736,0b7fa5eef2359f6c86a504f87bfe0e15ddc9b2616668c3be61e2ec1cec65f985,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\implementation-status.md,14670,08243231dcb0fd618af59ed123943e22bf985f2e4967a9ecf2e7e67bfe401198,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\indicators.csv,14969,2cf4a982c32befe5d703a332b9baf9ab35d91e53df47c9af0766ac0b94faf796,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\migration-proposal.md,8435,4983843c47a74ee206d8a5b697581f4288d81971a6452f5b438521ee6a3d44f4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\nonfunctional.csv,6333,51ba1bb3767bd2aeddcde2a88da6c373a3ed98a1082addacb05111a7950ef170,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\openapi.proposed.json,32636,5b4e76561f11ddc29bf6c1adf46fe2d923601cf62b1869b119c246f60a992743,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\README.md,7951,5bbfabd1ad0b34a05ce23afe2d466e8eec58c594c7345d2fc6380469b56b38a7,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\requirements.csv,22521,ac4d0da696fb4b562e2a832cc33883a9a870c5b4f730eadfdc0e652ff3fea9ee,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\skills-education-schema.md,7588,89276898fc606dff493724c3a9e33beb0be9dc7ae9448253d4ad6685052d30db,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\skills-functional-diagnosis.md,13135,8a271c555b67012f0e50ed71b5edaed8ffecf67919cd1cb6b440dea97d7781d0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\education\specification.md,63304,0419f22de21a328a8407660caab409695c35fd8868580a2e3331f35af45a85b6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\erd.mmd,24399,7373bf93e95db348b63192997d78ba1ce8414c95d6011c58312806022fc6e974,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\annex-de-execution.md,4387,8e5504eb242b54a8915c14d50f7dc4762e43df4fc7d3cdc353fffbac32a2ea2e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\browser-validation.json,723,4295fbe5ff0ff45429acde848f8af5632f15590be0114e3d6487d8b435a209de,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\canonical-integrity.md,3028,d9f89c386b9df543f8dc2099823a52b836d582fbec6e6e67e2b528b5e1759f9a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\compatibility.md,6456,9372a6be5d1ca7a71e98a032a8d3092fed8015e83df479f50999a4b90ffd403a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\form-schema.json,17645,45c3a18a7815b0cb29bc11a16a0a81ef3b692b38fef06664fd1024547b2f06dc,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\implementation-status.md,11833,6228c332b325cd9b71860db896c8e1ffbb2ef6c2a47f5792f0bf4c8e41ab3cad,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\openapi.json,134052,4c4e42306f85e8ea26bda21999e3b21dfc8560ee18f34c6cad0795ec9cea763a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\phase-1.md,8409,a9271a278e96034cb14189fa8169e0a5203df81933eabad59e4ca666fed9a44b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\README.md,21344,d7552eef64ac2628b9f3a81f219241205af74f2fd26796bdd3a5fbe0f600073f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\traceability.csv,2535,f5d449b5e317959bbd12b67a39faff1ca85cbc3e2395643d30dc9b0e035ba057,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\validation.md,4768,86514166a31c99a8d57531805ca894952d96491db0cf2a914b753ff01ce40584,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\verification-evidence.md,3874,f7535a947c9a92b3cddfcd4b3f6865b2123e7c08637fa99c0a28ea2de6c2a33f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\wizard-browser-validation.json,499,c177700ec3eb8d31a9024b83abadde343209a9fe3a14f6f6071ec8ee8c319f8d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\existing-business\wizard-implementation.md,15735,fc3aca9367dc714e0ec6771920aa1c784a212e1543b09747ba9e5cde2bc4e356,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\fiscal-source-references-2026-10-06.csv,9992,f2fde2257fd481f984e59bdfc62ce209c849b350961111616d2c2927c1421d6f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\frontend-integration.md,2619,a4250eb4d56c7c4a1893d974c72a1a6e423a09d8f5aff9498deb5ae2ea18efce,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\ine-import-status.md,7359,1298c29dc6aee460d03b45b0d1c883c81e2a123a295ffcf1b5de30a8edc3791d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\interactive-map.md,5607,5579a82b0d1008b6b5af034a8c216cadd3209e840de4f7f998545036b49c9a2a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\investment-dropdowns.md,5831,76cd7beec972a010fb17c3fd1f65cd6b268d8c3b5fed1c8fc62c54384f1624ca,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\map-coverage.json,2755,98475bf387143b988df9fa69f0453ec6eb6d93262716bc5b4d9b0d3cb6d46f5e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\opportunity-dropdown-browser.json,2924,dd605b3db0cee0f5a14b7260878a723bbf1b0bf55fb5af3a656d245fb74ff5ad,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\README.md,17375,c3d14064c552f338e4ce2480110a7d8dab4657f23b9f075a997f50edd2ff82c0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\source-manifest.example.json,247,cfd02f4c01174e799936234a897e65a6707c85217ebfa065e3805f56c20d2923,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\sql-workbook-inspection.json,655,c44a6edd502134fd6500b1907e81a1134560d59136099b9a6d843ffc91b09e46,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\sql-workbook-validation.json,787,42f0b796c911bff0289c19bba0683cf45d88c762b75bf54f9f9b730dff07a584,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\territorial-mvp.md,8069,16b46d4b0a66031f25701d2a8cc4327a0b43abc24f6db53da8d7394e04e8a4fd,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\territorial-openapi.json,49691,e0e27e7650f43b35ccbf9491e647aa744c860bb2a323fcfabb389d9a239dfcd6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\gis\territory-integrity-results.json,3783,8062e5d9975f6e8d16083b9c8ec06bcacba1add9d68de3136a99001e39a9a3d3,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\indexes.csv,40127,142728247045678e5f026cdebfed7e4cd69ebc637680b91380f4d3e0f7349dd4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\integration-repair-2026-10-04.md,12760,44d02093f1a97a006a18a9a7a41a9d093d6afb89ab1f128f893c3ca290eb83df,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\implementation.md,6487,84321b7d69d01a2eeca04efca0d791a204850e215c2781ee90ade882d14e26d1,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\legal-source-review-2026-10-03.md,14376,f9030854e6fe69b636ab61951643a8f9fdba4b5100eb454836eaa0a423e67e38,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\requirement-traceability.md,15535,ac3b3137123bcac34b4390df26d1474eb19bea8d6fd5ee0b156efd58d9a7ab15,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\land-assistance\source-inventory.md,8648,cbf0a5b0d55668f6ce18a3a03fd19478a2868c32482e2afc2dc2115ce37c4f99,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\legacy-schema.json,52671,4c6982432c7451d144ae1b03a8291e7796c977f698c8b809b57824aacf5d3629,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\legal-source-library-migration-2026-10-06.md,13327,ec3ac22cf2a374777c875e1cb46906596dc49b685fde00f6110f5f87333af38b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\malware-scanning-2026-10-05.md,10742,914b859d4cd1177e4085f7c96f59545de3e53adb6b8ba16ba725d4b84ddbffaa,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\management.md,5709,5d9e3c898949d510858a0eb6697b3b40c2d3b786ce063e3d1b2d5115a38a5ad6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\objects.json,10834,9d7613c948de2b1ba6f70b97472ac9f06ef445fb4d82ef1eaf3ca67dab239160,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\browser-qa.json,405,defb676b16f21eced0f715945a3fe770b63c8ac065b0738d9b4f68533f3d9249,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\contracts.md,3509,950bf6c89c0ab7f02bbfe804db4950a44cdfcac94af615aa1ef239aea517f2fa,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\README.md,5068,98c3be76059731061d17a8a2d5d3d33a3316331aecd6d37956bc073d9ab6c76a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\requirements.md,5339,17393cdd83da8ff46cc0accee7ad9465679e8ae7c7099897bf61a164fd1dfc18,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\room-1440.png,202889,5057540714b81f4618f0ea150febc77223d3fa91cf50050a83d18fad8b4b3501,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\partnerships\room-390.png,174441,754f21c816f960c1db6d7035dcf6ecec7c24064f43627deb08b31432a4b4394a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pii-extraction-review-2026-10-03.md,8638,d606cf522e8be973805529bb341c8a16d3bd70f161a5e97ec01324c25dc7f9cb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\authorized-opportunity-filter-browser-2026-10-04.json,915,b67e04eb2c9660ac23b74edc4e293d2bf3d7c5f9bff5527f9436a015b244c589,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\field-usability-pilot-2026-10.md,6408,b9b820c39bc4323ff19b9897b9cc533a38d76ab943ee9ff84054f62e0bd7f967,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\investmoz-catalogue-guide-browser-2026-10-04.json,2850,e5bd7c71a23a9bd7f6f5b61188cbd995b8115acdd7a6984b711446262d2d599c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\investmoz-guide-mobile-2026-10-04.png,326034,b5512909b6493b60013035187c950a7b396d5dfad8d3aec1099e4719da42c0f4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\private-dossier-association-browser-2026-10-04.json,343,d14327e8c37cc160cbc8ded3602970dd1a63932389984d2731777ca92f84f9bb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\private-dossier-association-browser-2026-10-04.png,417060,1e39c9a6bf377d537853024481d4e2d92a3907e185f51a89c695ef8abc3280ea,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-filter-removal-browser-2026-10-04.json,446,b3e15d696dd1c4d8fd3305395c48221971112a1579a5ea284edcdf32d06e42dd,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-filter-removal-browser-2026-10-04.png,447090,e9a1c971179fbdfaf95b4ffbb49f79eb5d45658c1c163d758dcde5cb305424c8,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-browser-2026-10-04.json,1595,8bc6045b45eef8b2e051b77f9c809517b29f1fe2b4f5eb1048182b930a48a05e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-desktop-2026-10-04.png,816346,c3ce06800fe438e481b11ea58c47e9c9a493091c4c5a303f2118c6c23d87954a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-filtered-2026-10-04.png,467961,8a31415585275ba6bccc623f6280e178c91e961dcda3037a51553e73d3e647c5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-filtered-mobile-2026-10-04.png,298053,e923261b8ecbec431a060e7bbcf49c95d43aa3e90cad15764d27664036179e26,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-followup-2026-10-04.md,6700,e7cd4e5cf3372aacd594da39bb2526c9bd393428a96e640594246fb515aa4708,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-mobile-2026-10-04.png,717500,545d3e39fcdbcdd9a24722d6d569508b410a1e9b2ffe96c7b63ab3b6675c8bcb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-browser-2026-10-04.json,987,e8023c8df2bdff4e29da8ee9cc26f035af9f18b5a48bc54b85d0a16013d5a347,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-desktop-2026-10-04.png,480868,af393579700ed3a7f29bc0ea06ff1f0316e2af6dcafcf8b325b1afdf721add30,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\pilot\territorial-search-positive-mobile-2026-10-04.png,367616,8afbbed084b57fcb20298d7aefc478336942b3ba7a0608287bdad34388711c30,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\portfolio-journey.md,8763,079dc2d9a5aa5384cf38680eef60876932f9e0a2e4260aa7a6dd8bec3fa6bdcf,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\production-reference-seeding.md,2422,b4c9585fc9470b1c0fc323417083c40cd9dce98946731c55c4e5a71a88a6bf3e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\public-portal-browser-validation.json,2180,7a30088ef81871d55d93e0cc3a348fd9cd0a9afc772bfb61572e829dd892561d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\public-portal-sections.md,7820,1b0a213480a9700f6f0dcb68bac5459f2e0af9cd274f2f2f43e62750e3d0f81b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\qa-database-target-incident-2026-10-03.md,5050,882547616032a06c6e876a0ef08e54d36018990c1f71d6ae6d4ed4dcb23969a0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\README.md,873,1cd4bfb21be5cda9bf2d66574ec05a71d1a7cf3acf4e78d2403cfc708b6a7ae6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\reference-schema-reconciliation.md,15940,0b3c93bade03cf395e5400d30e1d88da25921fbd9b9c79d180574d2b0d2f78ec,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\browser-qa.json,489,43df26a5719e03adffc463688313c0ee96536901851101984be6fc35c4ed035b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\cluster-1440.png,463640,bcf2059a862a3ee4866d05870eae80c0af9aa6b9a831b66d3fd94a7d7df046ec,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\cluster-390.png,256636,907b8e5ac1075f4cc8f4b34caf1a71170e68d8ff031e1527a8bbed9836bf541b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\README.md,11108,9794868e15c530a8e5ce1b5c16c8bdf6197a6c5526da2aaed4350ede77e27b5b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-1440.png,371150,914ce5df89ddc4a49d8f283041da3b21aa46a22436348683e78c08481e6f20d4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-390.png,341234,50504637502caffac0c82097006d8f526e8ff25d1d922e65008236abef490895,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships\territorial-browser-qa.json,284,26d1cde41c7a1be0f8394838917d627698ec2185b4ece095d365efa1a8c7e6c8,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\relationships.csv,11815,e236a15a8bd8b55ae2c7c74a7e66185066ac24708344f5836ebea88545a544e3,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\remediation-execution-2026-09-30.md,14937,c75582728aeb1d1490cf9a007745a87e540ecbc0f5082c7eb3ef4be85a7e8e5b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\requirements-audit.csv,57329,522507d7b2d491ce63440a7c9822d28adc41d8630e1136b945b3671ec55f7ecb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\requirements-audit.md,17494,1fc38e37528235a75789c92842995739474be58d96fe77bd5daecd1a449d8f88,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\roadmap\README.md,5113,df844466ee6e4c2a871191bbb2a3038b59d6c6fc307e42d27f434cfdbf60e5a9,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\roadmap\source-inventory.json,9580,348b0b2153cd9134d0cbb5f2604f6bca89c0816fcc6b078f96c86a77d6104891,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\runbook.md,4965,393bc08a00e6054d1881a256663ca25a487acffc16405b35441d5ac42da3a7e8,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\schema.json,419778,8881545beb64f48c7c1afe97d24744054bccfe9f698861d809c8e714a3bb29c4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\current-status-2026-10-03.md,61546,09da758c9d82751c5ca0edfe0656d8efaaa0c610ea3c6f1de45ee6dbccc0fb50,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\data-contracts.md,18346,714ebb4a4215af491de89a7251ece2db3d5b25f4770fede1a7b4af41614f4dab,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\entrepreneur-question-mapping-2026-10-05.md,11451,b374e20193ca20ee2b24fd53ab4bf4bb9c716bd2b519e2c6f419a4fe4eac9f70,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\fiscal-reform-2026-review.md,49068,b334895e6647c6776f54488fd03afd4e199f6bf6eb8c9ba4db52ab977f6fd618,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\investor-project-journey-2026-10-04.md,3839,5c3dedd8a32d21eb53c72172dea45b3760aaf62e4d8076ff71cc86a95370ed46,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\official-source-register.md,51676,8ffef016d4bcdc045e3e3f4ff827d1b014736a91fdd2139fabae88d70bc93a53,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\openapi.json,79479,a5ebb2ade09de0a9b620b58b1c1e3c14d0745505d127b563bd178bdd322948b7,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\primary-text-review-2025-2026.md,24783,e0a25324df6742dcd2a0b4ac57c79c86452ab87a64572893befeb321e322d78d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\project-dossier-print-qa-2026-10-04.json,894,bc41af7585ac4444b5fbf932c0dbc45a7740c6915555c0ae279c9df317335d0e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\project-dossier-report-2026-10-04.md,4989,2fc15d456bd12dde01b7dc1b287b30c4bed509a97b0c26f272088e291cadfe21,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\rule-governance-openapi.json,11400,fa52572acfb7703648f2590ca114fe6a6e8f53b64d6bd2253281f4f121d26bb6,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\rule-governance.md,9038,9fe043cd46258e470a30ba066245aa8a2a341821a426f0ed95da5dd2a7359896,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-after-forget-2026-10-04.png,119300,eab0f37d1c013c6200e623edbc46c17647f5a34dbd06a242f7942ee6bb9906de,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-before-forget-2026-10-04.png,148320,b57b5cc5f2e8b84a882230a139a660ca3412a4f67b766ac6d8d315ddff9fb456,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-active-browser-2026-10-04.json,1440,7fc66d67c69b862e2adc85feb897c07b33516089136781acdf3bc8ca78294e8d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulation-draft-continuity-incident-2026-10-04.md,6347,5f6086944e6fa6b310994e34ca32064e202f4911230cf5cab34441039dd61a1e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-a11y-browser-2026-10-04.json,3689,258c9e80b028ffb0ff6e3cb723c1cd6671dadc289baffce32e97e42771fbd676,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-api-errors-browser-2026-10-03.json,1598,840abac878be29b36cae7699a6fd764677ac75c902ab6d780ca009d1f3968342,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun-qa-verified.json,3689,7b34046113d90a8fb3078c51ac9f96b74f74720ed90010b389e09f201a705957,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun-runtime-verified.json,3689,5ef9e5c31795c6f0304f1483864f9c2ad685a0bebee59078f815efa7a7b7d3d0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03-rerun.json,3563,520c912342d25ee8412d969cae15d9745969f657709a31d042511a0915924d89,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-browser-audit-2026-10-03.json,3563,8671f4f23d1b55df0876de13476781cba79467ea9061e81814b0ed879f30744e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-calculation-browser-2026-10-03.json,2859,f5f64227fb7d5322e4a184e4a05052d032a4697d660cc86b0003514825c88092,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-calculation-responsive-browser-2026-10-03.json,37757,54771a108906d96491144df69933a4cc0da8cf125d2d88e367ebba38f4454397,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-cashflow-browser-2026-10-03.json,2978,4e78a67cbee67c1dae4ab6b19dd8e63b27560bde00deb8c66a3c868c8cc65146,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-continuity-browser-2026-10-04.json,900,30f261ffdb7f6e10c7305465166583820530b534f87933049cbbd3ffd281c495,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-final-validation-browser-2026-10-05.json,4293,3ecd4b3f1d2c212e5c2cc4d44270c25ba7d7b5c15952d89248f38b3171737e6f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\simulator-journey-browser-2026-10-04.json,4078,98af71bd0adbcb6729da7519d0a41457bb9b86c34568935fd7d57fef0dd8c06c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-248-I-Suplemento-1-2025.pdf,440018,ccf2a8deeca820f2dd076b4b2141b1efe3f6a806568c3a587ca59a8e92f4c251,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\BR-89-I-Serie-2017-06-08.pdf,9456358,11f0cab15eb6e51010952203ffa24fdc533a24fd642e19525fe4f46b17a1f5e5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\source-archive\Lei-22-2022-IVA-republicada-BR-250-2-suplemento.pdf,1834284,ea1b0dc6f5cf6e595f6d9a19e7042f398999e0087caef1785f6e8fac571b5f53,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-extension-traceability.md,6420,ecd8707ce939223f27245b88af75d349ff054582b92f7edf63691b5a7308dd0f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-gate.md,22365,e103c93808d7291b52f392dd7a2bf5bde8e1a1585d2402539f25f1e0c5fd270c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-10-technical-traceability.md,6748,21add6ba1bcd9e9229aeac7b3a1fb605186e88728baf767ebb9aa17319826c8d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-11-gate.md,7188,41015335082056a3fe8f0ac8d0a08512fb0d6b449a48a40a549f8c2cacab7c80,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-6-technical-traceability.md,10008,b651581dbbc9a4deebdf29306ddc41e854a8b94dfcda46f33f9ec5b2a231bac2,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-7-technical-traceability.md,11008,5c0ee04bfd55cb0a594af0234385f849fbc1b784b7a49345213419388deac582,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-8-technical-traceability.md,8036,e776a33e000f1787d7ac71616b0b2832339f5e8242a553d650f7c7310df11223,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-9-gate.md,6824,da2048d365ff9721d1104ccfdec10dc8802b8f02dedb1a3bb6e5417fe4d4961d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulations\stage-9-technical-traceability.md,6063,80d4adb5e4da8e6b740d6343332869c5d6d1a437bb213c2790a81ed7356cd560,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\simulator-evolution-progress.md,273004,625a0bcd98d72617656ddb71679e12fca2d3ed23a6bc55782c32ae972c8a2b9f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\source-reconciliation.json,372,53783524c4eb928cd1eaa5c575a6f45fca4f1dee8b3aeb0be6d874807e177748,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\source-staging\pii-26-30-review-only.csv,101415,a46e658cacce19a387fb314842150693f4020f479ad14192282205d5e71ce3c3,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\source-staging\zone-integration-2026-10-04\Pasted text.txt,9346,2453530cc98ffd9b270eef47786a9d596701e4831e2a3c16c3765152cc916494,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\architecture.md,13447,4a282fb574af39cce16a5f4f14324699bb13469c8639a221464232718ecf6597,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\client.md,7995,9767c99c96c3660fcaa98f39df1db58f47a6bb5a802c4ea966fdc26bd45068ac,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\mapping-catalog.md,18692,39505269ba8cec49cf0642e9b603a31912a1ba0c06ee2d7969cc21333febc6a0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\suitecrm\outbox.md,4795,3c0bde5e1dc9e0352f060ba37d58f822a7cc1eb1b2df52fa881928e088b05bbb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\table-catalog.csv,9934,45ef0a893111afd342963d8240ca17fb276a090e92efd1ad2ab41d6a48c8e9d1,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\territorial-search-audit-2026-10-04.md,7237,704e41a660afc1eb774d6320d5681ee5f348aae6651d3b5cae3c8989bbe38d55,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\traceability.csv,88017,4ad83685122a63d90c77eb2c1be2858861b61bdde4c2300012734482af77ef8f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\browser-validation.json,5045,4ca6419b44a6fea847212916af59ae6672c0ad062cb2daf535acb2a90d15f0b5,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\data-and-operations.md,14690,e63e32831b0dc4172f1b7f4a028c45c3b2de99dfdaca6ae3eb408a426cd9cba4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\local-latency.json,952,ec0e2d6f35b02d87c1a56150da7135efa6067c11ccc64582e15e2275b33be92c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\openapi.json,191844,ed1ba3868a71ea1ca0f6e2aa8f0ac5199dd60dfde5cbe6e2cc359baa4ff9cf0a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\public-browser-validation.json,2615,f18a29cf9b7ff5978ca2e7b4fb53dd624de5f68a2e573c0282b52fdea94a7bc0,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\README.md,9760,1dbda44d61d217f0179127fd128c2daf5bd5028a28f5bd240f3113f2a865173a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\traceability-and-manual.md,13614,66e5bf20cf423c58b923753290e30903265905a2eac69995777296bd19757d6e,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\unification\validation.md,5778,999cca6894fe87ab0f579a1d248764a2af5a412049536cea51db20c0a07aa90c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\upgrade-progress.md,13050,c33a1d528fe234677f267cd3874c83d87bca5e2fdc143f20c63306ab10297fad,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\ativacao-rastreabilidade-territorial.md,12206,904787c7040c29f7410d599fe357319afc559baba5c68dc319ade17d21e801d4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\ativacao-segunda-entrega.md,8837,c8acd38715c26b13b563afbc8ee02851c929af9448d2e78cb1656d16988803d7,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\backlog-mestre.md,49028,8bcc5e66de95426dbb291d8a380e86d0f4a3ef0e3e70b48ad6c7d9e31893c7b3,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\consolidacao-nove-diferencas.json,10320,d9f474c0dcae06e78b71c720611b16a2a0ec0d6b83bfd9c83558781eb130f0cf,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\consolidacao-variantes.md,7958,3defe7f46aeaa37da2f06f5c358da83f48ff4656566d4044bfe7cfb0ad50d5b2,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\ficheiros-primeira-entrega.csv,15338,b8c6eefb8fe879df7637bcda4aa4d458254edd82aceaa86991b5d885c046ee0a,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\ficheiros-segunda-entrega.csv,3345,a7445854213ad91cf5a929237dc7c2ab2f2f682f5eb014cd10c4f9623ac30d20,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\gestao-oportunidades-dashboard.md,13951,a12b57985e779180860983968922941bac9db3ab91aa4977d4ccf2b5b6d74997,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\indice-documento-mestre-atual.csv,151889,35ffb5d727f8ab1811ac946c2f89c2e95a74108b9a9cfbdd688a29fffee6080f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\indice-documento-mestre.csv,153757,4c13f1efd25a130c0d63e4a7f2efd9f9c2fbe9eb7ddee452534f06e8d7759bdd,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\oportunidades-correspondencias.md,15378,3812fe47bf667a5323363cbfc7c0b329c1f717f4ea814a6e3c454e6624224a72,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\origem-oportunidades-e-separacao.md,7039,83c37556b898e3e2f52b272f515d2e10830218b133298dd7086c6b380bae418c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\primeira-entrega.md,12287,91af08a26aff26afd420c3fd9164d391014ef224b19db5dbe0f00758a2ecc571,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\primeiro-percurso-ativo.md,17401,432b134b6aec7612776d510fcc9c38d8d566eadf821928994b60ed717e0eb84d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\qualidade-territorial.md,48392,6bf7866d3946b6c99f8c3ba2c6bc0b633d54d4da5b9369a4883e06d6e30bffa8,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\reconciliacao-documental.md,5009,dab706f8e0b6a66e6cd3fde2bc8989d9f56bd6ad3f4e34f9fec52db6e38eaec4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\reconciliacao-fontes-territoriais.md,97710,3733136a7a2696b2cea4e9ac4ba5e0891369ff8969497ed87cd2962084323ee4,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\recursos-oportunidades.md,10792,7829ad26ad1060710426706b05c9dfbdf1912a08ca190b23c8662bba5827c632,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\releitura-documento-mestre.md,3985,e7f743c0e28a07146e391e20675360c52ba9272cbc4875e8d74b7116946e590b,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\repeticoes-reconciliacao-atual.json,235914,9166ebb15935153b33f60021a8b008ab8479ca0671640af28a9e87138bfd5758,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\repeticoes-reconciliacao.json,278145,1f49b0ae5e4cfd95c60011d6af4a16a5d6f7ea2c13446ff1d5224ea66343fe59,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\repositorio-legal-jornada.md,3245,1729692568c02aba71f246e20e842175bbb78795645f762091e679f3fe77b056,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\revisao-funcional-transversal.md,11226,90ed3ac0021863aa92a864e1cef754ec45e16667f595a7fd26f771290325e44c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\v2\revisao-origem-oportunidades.md,5942,1feddb2d78b8a04f2aa46151784a3643ceea08b7f9b52935ff336745263a4cdf,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\validation-results.json,5131,8a35788bfda5fd7782f269f60c963b909e152d55880d3d090cc960a5d52a8605,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\validation.md,2958,b9d1ec9d4f8f8879ce9c650a8ba59a811065fe7b7e3f53f201fb64151533fec2,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\verification.sql,1732,d15685b13971cb526cdcef65c8511e79f9de7da28074450dea1bb5654bc69596,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\baseline-data.json,3528,72736fbe37f8237fad1ee0a1f6dd97709c8d0464862d2635a6ef51c6bf8b18fc,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\baseline.md,7117,db6df0dff91244ff950acbc9a285b4bb17038d9514141e236c12286cbe97b617,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\browser-validation.json,2976,b89e20bb6f0710e9e1ef0e7392790320da1bea936463a3bbc205dc9b2016c12c,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\current-data.json,3910,81d25d5de6f22a01c55b8e945efd6626c9ca61bf9039cc93995ff00cbbf1a9fb,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\data-dictionary.md,4418,d851147c7b36b738a92f91f6c697e49d4b5855ce42a474ffa9e672c90f445986,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\diagnosis-and-adr.md,7962,c5a1a40aa17d2793d5c529a634770d2ca3f934ba18677703d741ef800907935f,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\implementation-status.md,7694,263b86d4eeb98c7996674a0a26e070c50c4f6f7638ac1c4d810262ac0adafc19,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\industrial-parks-reconciliation-2026-10-04.md,12705,b6aad32e2330edabd8f7c06e7cd75dc7a8faf5dd1be657676e9db5670d1648e9,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\integration-2026-10-04.md,10944,a74fe74d871f0692ecfbfc79a62309e0fda9bec5cb43757897cf589aafbee076,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\legal-matrix.md,2918,1178627b7f57c31e837688360cf0d2dc02b010a0114f3a8007c25e7fa843c0a1,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\openapi.json,93753,314cc7171e75d37d22afc9042e175db71b373bb94c0d1becc4c08fc1a73d414d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\operations.md,5020,d0480f301875b84f144e272b2a41c67cf2d13bc15ffd8fb5141e8d4c5c584f66,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\phase-1-attachments-qa-2026-10-04.md,6110,abfb7a9925886f5c4faa88350038f13babf8cc2bc27cf49c1e9e9d92db700bc8,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\plan-and-traceability.md,11977,4516ea21664f2c0b56f5185515b6e05a1292377a92d0fe4123b1ed97639f3c10,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\README.md,3529,cab2d4152ffd7772bab56c5caa98261ad497be58696594fc9e0d4d9e909aeb88,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\validation.md,2987,bcf73cbc4ef5ef4660ab008c64f348ba3c2e3d77d15ec0c04617fe851d11080d,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\docs\investmoz\zones\zone-catalog-active-empty-2026-10-04.png,79809,285108e8ac37bd2ccf546d67f72d9f73aed3f9ff26597d68db0ffb514b163855,original,,Documentação do repositório,Nenhum cálculo ativado pela auditoria,Situação documental não determinada por inventário,
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-adm1.json,15442,41efdc512ba971d6ca3b447d929e04c86d85ea8af1dc6c13bde419ec4533e448,original,,Metadados/candidato geográfico inventariado; seleção e publicação não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-item.json,1513,4f95009b98c7979fecfa0986a38bf77e660376f98bcfd70d7369bbf363298af3,original,,Metadados/candidato geográfico inventariado; seleção e publicação não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-moz-service.json,5929,67168029d5f559d926b8b3c432729a8973cf1dd2868826e86d756a0c53c2ea4c,original,,Metadados/candidato geográfico inventariado; seleção e publicação não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\arcgis-source-search.json,30681,247f600f88a30a7052c62b489d98889e49f55f75759c07d3f8e992418ef5cf0a,original,,Metadados/candidato geográfico inventariado; seleção e publicação não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm1-ine-20190607.geojson,5254315,ce5cd5f6090b7ba9ac78f919c9dd149f6c7880ab8275051a3398b1c6593fa989,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm1-ine-metadata.html,5769,de118cda24c594402adda6f11143ce236f928502b096cca45be7f5897b3ecbcf,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm2-ine-20190607.geojson,18086741,16781986ac938bc8e81c9ca01a076b4bd46e333e8877645844d0cc7cd2919707,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm2-ine-metadata.html,5958,5df480267f2bc98a734d6a0a9b2531ded59cea715501006d2f869c35a12cd420,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm3-ine-20190607.geojson,26773796,ef11737c1ef68870bfcee67903352b7e554cb40ca39dd85f020c2a13631e1635,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\moz-adm3-ine-metadata.html,6063,1366696c41e95fd3ffaa7190764e7bee82ad5cacc062d9f66b74090bb0da7431,original,,Exemplar INE/UNOCHA 2019-06-07 conservado privadamente em QA; fonte oficial identificada aceite; publicação/vigência atual não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,2019-06-07
+C:\laragon\www\portal-investidor\storage\app\private\investmoz-v2\portal-audit\unfpa-moz-adm1.json,15458,a723d8745e6c1b66f5b374839dba9863ead819f2e65279b1bbd32a8cee8db47a,original,,Metadados/candidato geográfico inventariado; seleção e publicação não inferidas,Nenhum cálculo ativado,Vigência atual indeterminada; edição histórica preservada,
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\O InvestMoz deve funcionar como um assistente de investimento orientado por etapas e regras de aplicabilidade.docx,1327814,aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364,original,,Exemplar integral lido para proposta; publicação não inferida,Especificação funcional; nenhum cálculo ou regra jurídica ativados,"Documento de programação do responsável, não diploma oficial",Exemplar identificado por SHA256; data/edição interna não identificada
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\Relatorios\O InvestMoz deve funcionar como um assistente de investimento orientado por etapas e regras de aplicabilidade.docx#word/media/image1.png,1288315,1da7d5a84162f3a4772e1f58a5dc4af701694e92ee3110a6530288916f728d80,anexo embebido,,Exemplar integral lido para proposta; publicação não inferida,Especificação funcional; nenhum cálculo ou regra jurídica ativados,"Documento de programação do responsável, não diploma oficial",Exemplar identificado por SHA256; data/edição interna não identificada
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\~$stao de perfis investeMOZ v1.docx,162,22ba2556e44ab7825813bdf71bb6813ea2b7696b3b1681dc3fb21c87da96ad91,original,Inventário complementar 10/10/2026; versões anteriores preservadas,Acessível localmente; importação/publicação não inferida,Nenhum cálculo ativado,Situação jurídica/documental não inferida do inventário,Exemplar identificado por SHA256
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\~$ompt a serem aplicados .docx,162,e726ad6723df9f664121d97e18854466b30efd24a1f8efab0a7945cbecf7059b,original,Inventário complementar 10/10/2026; versões anteriores preservadas,Acessível localmente; importação/publicação não inferida,Nenhum cálculo ativado,Situação jurídica/documental não inferida do inventário,Exemplar identificado por SHA256
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Gestao de perfis investeMOZ.docx,46648,283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855,original,Inventário complementar 10/10/2026; versões anteriores preservadas,Acessível localmente; importação/publicação não inferida,Nenhum cálculo ativado,Situação jurídica/documental não inferida do inventário,Exemplar identificado por SHA256
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\~WRL4044.tmp,46970,87fee09bb7e547d7aeebe7de984681fb52e588c74988da7ebe0ac72048e73a22,original,Inventário complementar 10/10/2026; versões anteriores preservadas,Acessível localmente; importação/publicação não inferida,Nenhum cálculo ativado,Situação jurídica/documental não inferida do inventário,Exemplar identificado por SHA256
+C:\Mac\Home\Documents\TEMPO\Portal Tempo\Servicos Tempo\prompt\novos\Gestao de perfis investeMOZ v1.docx,50215,f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38,original,Inventário complementar 10/10/2026; versões anteriores preservadas,Acessível localmente; importação/publicação não inferida,Nenhum cálculo ativado,Situação jurídica/documental não inferida do inventário,Exemplar identificado por SHA256
+C:\laragon\www\portal-investidor\docs\investmoz\v2\auditoria-portal\propostas-perfis-modulares-sla.md,17568,1fa569e1c02d0e204f98e58252babefc2e7f0391265215e5e49e7566026620c2,proposta interna QA,"Documento integral; regras/fundamento/efeito/decisões efonte§25.4. Não fonteoficial,nenhuma aprovaçãoinferida.",Consulta no repositório; publicação não inferida,Nenhuma regra/SLA/cálculo ativado,"Proposta para decisão, não ato jurídico",proposta20261010v1
diff --git a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
index 100436c7..a498b530 100644
--- a/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
+++ b/docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv
@@ -3265,10 +3265,10 @@ OP-FIELD-geoValidationRequest-checks,"Persistir, validar e recuperar geoValidati
AUD-FIELD-001,"Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/interactive-investment-map.tsx:38; const map = useRef(null);","Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores",governação/outros,/api/v1/investment/admin/interests/{interest}/status; /management/history; /management/interests; /management/interests/{interest}; /management/interests/{interest}/consent/contact; /management/interests/{interest}/consent/proponent; /management/opportunities; /management/opportunities/create; /management/opportunities/drafts; /management/opportunities/{id}/draft; /management/opportunities/{id}/edit; /management/opportunities/{id}/lifecycle,resources/js/components/interactive-investment-map.tsx:38; const map = useRef(null);,Requisito transversal; consultar estado-ativo-after.json,; suite global QA e GET por perfil disponíveis. Evidência do domínio não demonstra integralmente esta cláusula; UI individual pendente.,parcial,Inspeção visual individual ainda não executada; inventário de chamada não demonstra pesquisa/recuperação/uso cartográfico.,"QA de UI quando browser disponível; reutilizar o domínio existente. Dados/decisões específicos no backlog, sem segunda validação de fonte oficial.",AUD-FIELD-001: Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação,P1,AUD-FIELD-001: Consumidores independentes; componente comum não demonstra todos os usos,AUD-FIELD-001,1,"[{""id"":""AUD-FIELD-001"",""pedido"":""Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/interactive-investment-map.tsx:38; const map = useRef(null);"",""fontes"":[""Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores""],""aceitacao"":""Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação"",""estado"":""parcial"",""variantes"":""Consumidores independentes; componente comum não demonstra todos os usos"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-FIELD-002,"Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/interactive-investment-map.tsx:62; '© OpenStreetMap contributors',","Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores",simuladores,/api/v1/questionnaires/{code}; /api/v1/simulation-drafts; /api/v1/simulation-drafts/claim; /api/v1/simulation-drafts/claim-preview; /api/v1/simulation-drafts/current; /api/v1/simulation-drafts/linkable-businesses; /api/v1/simulation-drafts/{id}; /api/v1/simulation-drafts/{id}/business-link; /api/v1/simulation-drafts/{id}/conversions; /api/v1/simulation-drafts/{id}/touch; /api/v1/simulations; /api/v1/simulations/history,"resources/js/components/interactive-investment-map.tsx:62; '© OpenStreetMap contributors',",public.simulation_form_drafts: 22 registos; public.simulation_scenarios: 16 registos; public.simulations: 16 registos; public.simulation_tax_rules: tabela ausente,"SimulationExecutionTest, SimulationFormDraftTest, SimulationDraftContinuityTest, SimulationTaxRuleGovernanceTest; suite global QA e GET por perfil disponíveis. Evidência do domínio não demonstra integralmente esta cláusula; UI individual pendente.",parcial,Inspeção visual individual ainda não executada; inventário de chamada não demonstra pesquisa/recuperação/uso cartográfico.,"QA de UI quando browser disponível; reutilizar o domínio existente. Dados/decisões específicos no backlog, sem segunda validação de fonte oficial.",AUD-FIELD-002: Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação,P1,AUD-FIELD-002: Consumidores independentes; componente comum não demonstra todos os usos,AUD-FIELD-002,1,"[{""id"":""AUD-FIELD-002"",""pedido"":""Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/interactive-investment-map.tsx:62; '© OpenStreetMap contributors',"",""fontes"":[""Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores""],""aceitacao"":""Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação"",""estado"":""parcial"",""variantes"":""Consumidores independentes; componente comum não demonstra todos os usos"",""modulo"":""simuladores""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-FIELD-003,"Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/investment-map-panel.tsx:51; ","Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores",governação/outros,/api/v1/investment/admin/interests/{interest}/status; /management/history; /management/interests; /management/interests/{interest}; /management/interests/{interest}/consent/contact; /management/interests/{interest}/consent/proponent; /management/opportunities; /management/opportunities/create; /management/opportunities/drafts; /management/opportunities/{id}/draft; /management/opportunities/{id}/edit; /management/opportunities/{id}/lifecycle,resources/js/components/investment-map-panel.tsx:51; ,Requisito transversal; consultar estado-ativo-after.json,; suite global QA e GET por perfil disponíveis. Evidência do domínio não demonstra integralmente esta cláusula; UI individual pendente.,parcial,Inspeção visual individual ainda não executada; inventário de chamada não demonstra pesquisa/recuperação/uso cartográfico.,"QA de UI quando browser disponível; reutilizar o domínio existente. Dados/decisões específicos no backlog, sem segunda validação de fonte oficial.",AUD-FIELD-003: Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação,P1,AUD-FIELD-003: Consumidores independentes; componente comum não demonstra todos os usos,AUD-FIELD-003,1,"[{""id"":""AUD-FIELD-003"",""pedido"":""Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/investment-map-panel.tsx:51; "",""fontes"":[""Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores""],""aceitacao"":""Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação"",""estado"":""parcial"",""variantes"":""Consumidores independentes; componente comum não demonstra todos os usos"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-FIELD-004,"Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/components/investment-territory.tsx:160; form.setData('payload', { ...form.data.payload, declared_origin_country_code: value })} />","Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores",governação/outros,/api/v1/investment/admin/interests/{interest}/status; /management/history; /management/interests; /management/interests/{interest}; /management/interests/{interest}/consent/contact; /management/interests/{interest}/consent/proponent; /management/opportunities; /management/opportunities/create; /management/opportunities/drafts; /management/opportunities/{id}/draft; /management/opportunities/{id}/edit; /management/opportunities/{id}/lifecycle,"resources/js/pages/desk/request.tsx:172; form.setData('payload', { ...form.data.payload, declared_origin_country_code: value })} />",Requisito transversal; consultar estado-ativo-after.json,; suite global QA e GET por perfil disponíveis. Evidência do domínio não demonstra integralmente esta cláusula; UI individual pendente.,parcial,Inspeção visual individual ainda não executada; inventário de chamada não demonstra pesquisa/recuperação/uso cartográfico.,"QA de UI quando browser disponível; reutilizar o domínio existente. Dados/decisões específicos no backlog, sem segunda validação de fonte oficial.",AUD-FIELD-009: Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação,P1,AUD-FIELD-009: Consumidores independentes; componente comum não demonstra todos os usos,AUD-FIELD-009,1,"[{""id"":""AUD-FIELD-009"",""pedido"":""Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/pages/desk/request.tsx:172; form.setData('payload', { ...form.data.payload, declared_origin_country_code: value })} />"",""fontes"":[""Pedido direto 09/10/2026, §1 cartografia em todos os campos; inventário de consumidores""],""aceitacao"":""Demonstração individual em 1440 e 390 px; selecção respeita pai e ID guardado; ausência de geometria mantém indeterminação"",""estado"":""parcial"",""variantes"":""Consumidores independentes; componente comum não demonstra todos os usos"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-FIELD-010,"Pesquisar, selecionar, guardar e recuperar no consumidor resources/js/pages/desk/request.tsx:186; 0; null422. Camposreadonly/verified/land_sale recusados. Ligações/contacto/hierarquia/hash/scan/parcelas validadas. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado. | [Instalação/cartografia QA 10/10/2026] profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.",parcial,"Histórico até09/10 (preservado): Não duplicar cadastros nem tomar simples seleção da categoria como módulo concluído | [QA independente 10/10/2026] Implementar adaptador de IDs existentes, validação modular Create/Patch/gates e estados/transições/permissões/versionamento/revisão/aprovação/publicação separados. Nenhum destes critérios fechado pela extração do schema. | [QA dashboard 10/10/2026] Completar formulário, vínculos canónicos/documentais, condições finais §26,Create/Response e demais módulos DUAT/transação. Dados parciais guardáveis não validam viabilidade nem decisão externa. | [Perfis v1 QA10/10/2026] Critérios específicos preservados; não confundir workflow parcial/props de menu com submissão/aprovação/publicação completas ou demonstração visual. | [Workflow QA 10/10/2026] Formulários/grids e validações semânticas adicionais do §25:valorações completas, comunidades/consulta, beneficiário efetivo/financeiros existentes, compatibilidade cadastral e urbanística, NDA/teaser, Response integral e editores ainda incompletos. Perfis concession/financing/supply/other não configurados; não inventar contratos. | [Semântica QA 10/10/2026] Visual por categoria; correspondência documental/cadastral e urbanística exige evidência/gate humano; não compara automaticamente titular e teor do PDF. Aplicabilidade de unidades/limites/materialidade ainda não expressa por regra inequívoca; Response integral/§27 permanece aberto. Quatro perfis modulares sem decisão. | [Instalação/cartografia QA 10/10/2026] Response integral/§27 e condições por tipo/unidades, urbanismo/materialidade e entidade sem exercícios ainda parciais. Propostas D-M1–M4/D-S1–S2 requerem decisão; quatro categorias não submetem/publicam até perfil aprovado e adaptador demonstrado.","Histórico até09/10 (preservado): Dados concretos do objeto/direito/mandato; nenhuma credibilidade oficial reaberta | [QA independente 10/10/2026] Reutilizar OpportunityManagement/Resources, JSONdraft/version, usuários/policies/audit_events e serviços fundiário/negócio/documentos/territórios. Preparação paralela e decisão externa distinta; não requer CRM externo. | [QA dashboard 10/10/2026] Reutilizar documentos/direitos/objetos/negócios/territórios existentes; não renumerar bigint para exemplosUUID. Sem nova decisão para implementar emQA. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",AUD-OP-04: Campos/coleções específicos da categoria persistem e validam com vínculo canónico,P1,AUD-OP-04: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-OP-04,1,"[{""id"":""AUD-OP-04"",""pedido"":""Contratos especializados imobiliário, DUAT e transações"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Campos/coleções específicos da categoria persistem e validam com vínculo canónico"",""estado"":""não implementado"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""oportunidades""}]","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Categorias existentes; campos/gates/workflow especializado não implementados. | [QA dashboard 10/10/2026] Formulário especializado ainda ausente; nenhuma prova visual ou contrato integral atribuído ao adaptador API. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes. | [Instalação/cartografia QA 10/10/2026] Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Contratos normativos preparados; validação/transições especializadas não implementadas. | [QA dashboard 10/10/2026] real_estate parcial no POST drafts/PUT draft existente, com tipos/enums/limites/UUID e campos de resposta recusados. Condições finais/Create/Response/referências canónicas NÃO estão completas. | [Workflow QA 10/10/2026] 10categorias guardam rascunho incompleto e recuperam noutra sessão MFA. Create/submissão passa6(investimento,imobiliário,DUAT,venda,parceria,franquia);4 recusadas por falta de perfil modular aprovado. Venda exige preço>0; null422. Camposreadonly/verified/land_sale recusados. Ligações/contacto/hierarquia/hash/scan/parcelas validadas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado. | [Instalação/cartografia QA 10/10/2026] HTTP 18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Nenhuma migration ou alteração de oportunidades deste lote; artefacto não ativa módulos. | [QA dashboard 10/10/2026] QA14: contrato parcial imobiliário em management_draft; PATCH preserva valores anteriores; nenhum estado submetido/aprovado/publicado. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada. | [Instalação/cartografia QA 10/10/2026] Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:operação sem alterações DDL. Recursos/originais e15geometrias gravados somenteQA.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Artefacto legível e rastreável; não existe percurso funcional especializado demonstrado. | [QA dashboard 10/10/2026] GET edit devolve values.real_estate depois de logout/nova sessão; outro perfil403. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada. | [Instalação/cartografia QA 10/10/2026] Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.",Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Não implementado funcionalmente; estado canónico mantido. | [QA dashboard 10/10/2026] Campos privados recuperados por props; ainda não há apresentação/edição por controlos especializados. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente. | [Instalação/cartografia QA 10/10/2026] JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.,"Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada | [Instalação/cartografia QA 10/10/2026] Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados."
+AUD-DASH-01,Dashboard integrado por perfil com ações úteis,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",dashboard/perfis,/dashboard; /management/opportunities; /balcao-virtual/painel,"DashboardController; PortalMenu; gestão existente | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos. | [QA dashboard 10/10/2026] C43: AppSidebar omitia todos os filhos exceto primeiro destino de cada grupo; Painel apontava/investidor também para gestor; criação no fim com labelCriar oportunidade. Atalhos/dashboard/menu agrupado corrigidos reutilizando props autorizadas; Painel da gestão→/dashboard,dossiers→/investidor. FlagQA e build separado; área privada preservada. | [Perfis v1 QA10/10/2026] Reutilização/permissões organizacionais e workflow parcial nos AUD-PROFILE-01–32; nenhum sistema paralelo de identidades.","investment_accounts: 0; investment_company_declarations: 0; investment_submissions: 3 | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada. | [QA dashboard 10/10/2026] Leitura SQL REPEATABLE READ READ ONLY10/10/2026: investemoz:5432;020000 instalada,030000 ausente;6 oportunidades publicadas. Contas2/13 autorizadas e verificadas. Manifesto ativo75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94 preservado;flag do incremento false. Perfil/URL da sessão reportada ainda não confirmados.","QA GETs por perfil e provas históricas de navegação | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Painel composto e /investimentos preparados atrás de flag desativada no ativo; projeto recente, pendências, documentos, resultados/tarefas e próxima ação. Gestão preservada. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente. | [QA dashboard 10/10/2026] dashboard-opportunities-http-qa.json: dashboard→destinos anunciados→create→201→GET→logout/nova sessão→GET→PUT→arquivo→filtro archived→restauro; QA13 mantém ID,4 eventos. dashboard-manager-mfa-http-qa.json: gestor17 MFA em duas sessões/reload/logout,0 registos alterados. 12 oportunidades anteriores, relações/documentos/dossiers preservados por SHA;6 publicadas mantidas. browser_visual_observed=false. | [Perfis v1 QA10/10/2026] Dashboard→novo draft15→recuperaçãoMFA→coedição21/22 HTTP; tipos/org/multirrole403; requestArchive persiste. Submissão422 por contrato completo ausente. VisualC37/C43/A-B pendente. | [Workflow QA 10/10/2026] Consumidor oportunidades:Promotor21, contrato/localizaçãoMZ/documentos/refs recuperados por categoria; APIprivateboundaries existente. Não encerra países/origem/estatísticas por outros formulários, 188lacunas cartográficas nem render de mapas. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,"Contadores/workflow avançados e inventário visual de todos os botões pendentes | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B. | [QA dashboard 10/10/2026] C43 corrigido em QA/backend/assets, sem ativação; interface e identidade da sessão reportada pendentes. C37/A-B e demais ações do dashboard continuam abertos. | [Perfis v1 QA10/10/2026] Critérios específicos preservados; não confundir workflow parcial/props de menu com submissão/aprovação/publicação completas ou demonstração visual.","Não atribuir permissões ativas para ensaiar | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente. | [QA dashboard 10/10/2026] Ensaio visual autenticado em18097. Gestor requer email em portal.managers+verificado; não elevar investidor18 por causa da ausência do menu.","AUD-DASH-01: Ações permitidas por perfil; foco/teclado/móvel; indicadores e destinos reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-DASH-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-DASH-01,1,"[{""id"":""AUD-DASH-01"",""pedido"":""Dashboard integrado por perfil com ações úteis"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Ações permitidas por perfil; foco/teclado/móvel; indicadores e destinos reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""dashboard/perfis""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente. | [QA dashboard 10/10/2026] AppSidebar+dashboard corrigidos; validação visual do layout/atalhos/teclado/móvel pendente. API e HTML não equivalem a clique.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas. | [QA dashboard 10/10/2026] Links descobertos da resposta de /dashboard e seguidos no servidor18097. GestoresQA14/17 autorizados;QA13/18 não são gestores; investidor/unverified/guest não ganham gestão."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa. | [QA dashboard 10/10/2026] Percurso de oportunidade QA13 conserva dossier privado e seis versões públicas; testes de negativa preservam dados."," | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente. | [QA dashboard 10/10/2026] Nova sessão/reload do gestor17 com MFA mantém oportunidade13; outra conta403."," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente. | [QA dashboard 10/10/2026] Manifesto ativo preservado; HTML QA aponta build-qa-opportunities e version hash próprio. Perfil da sessão do relato ainda desconhecido; sem atribuição de causa a essa conta.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-DESK-01,Criar/editar/recuperar dossier e pedido com feedback,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas",Balcão/orientação,/balcao-virtual/painel; /balcao-virtual/dossiers/{id}; /balcao-virtual/pedidos/{id},VirtualDesk; desk_cases/requests/messages; tarefas existentes,desk_cases: 1; desk_requests: 0; desk_institutional_links: 0; desk_messages: 0,"PortalAuditConsumerLotTest: 2 testes/124 asserções; phpunit-lote3-final.xml; geometry-consumers-lote3.json: 361 limites reais recuperados em QA, zero divulgação pública; visual não demonstrado | [Semântica QA 10/10/2026] Provasdeledger/colunas/definição:dashboard-active-readonly.json e opportunity-semantic-environment-qa.json;preservação18coleções/MFA18/manifestoativo:profiles-v1-preservation-qa.json.",parcial,C21: país do requerente e devolução de país/origem corrigidos nos três serviços em QA. UI atual e restantes ações/anexos por perfil continuam pendentes; não afirmar o percurso inteiro do Balcão concluído.,"Serviço interno real e dono/responsável; primeiro pedido só com dados do utilizador | [Semântica QA 10/10/2026] Leitura ativaREADONLY10/10:020000eBalcão07/190000+08/120000instalados;030000não;040000não;09/190000prepare_investor_pathausente(ledger/2colunas/definição). QA03/04/09-190instalados;definição19etapaspublicada61000919-0000-4000-8000-000000000001 SHAe0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf. 09/190000nãofoi substituída:continuanecessária paraativo e não se repeteQA. 030/040semdependênciaDDL190;190dependeBalcão/journeys/steps/questionnaire_versions;workflowusa020+030+040+tasks/catalogue. Planofuturo:visual/candidata→backup/restaurofrescos→códigoflagsfalse→030autenticada→040instalador/bootstrapautenticadosaindaemfalta→190apenasfaltantesvia/management/balcao-install→dadosreais/perfis→cartografiaprivadaidempotente→flagspercurso/oportunidades→publicaçãoseparada. 0fixturesQAnoativo;readytrueépreparação;semativaçãoautorizada;reversãodesativaflags/preservahistóricoourestaurabackupverificado,nãodropusado.","AUD-DESK-01: Criar uma vez, guardar versão, recuperar em sessão nova, corrigir 422, transições e mensagem explícitas",P1,AUD-DESK-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-DESK-01,1,"[{""id"":""AUD-DESK-01"",""pedido"":""Criar/editar/recuperar dossier e pedido com feedback"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas""],""aceitacao"":""Criar uma vez, guardar versão, recuperar em sessão nova, corrigir 422, transições e mensagem explícitas"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Balcão/orientação""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-DESK-02,"Reutilizar investimento, percurso, pedido e responsável no Balcão","Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",Balcão/orientação,/balcao-virtual/painel,"Contextos da conta; investor_journeys; interest_requests | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","desk_cases: 1; desk_requests: 0; desk_institutional_links: 0; desk_messages: 0 | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","QA InvestorGuidanceTest | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Entidades existentes reutilizadas; dados do simulador por ID/versão e descrição prefills no Balcão com evento e hash. Resultados financeiros privados com entradas congeladas, recuperados pelas fórmulas existentes. Prefill de todos os campos/consumidores ainda incompleto. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C35: campos data/emissor opcionais omitidos causavam500; corrigidos sem inventar dados. C36: original cifrado clean devolvia404 em consumidores por comparar ciphertext ao hash original; VerifiedDocumentBinary partilhado recupera bytes verificados, mantendo permissões/cifra. document-consumers-real-qa.xml: PortalRealDocumentConsumersTest (ClamD real) verifica biblioteca privada→scan→classificação→publicação separada→download,409versão/dedup/404hash/403gestão, Balcão upload→scan→download/dedup/confidential/403estranho, reutilização do original cifrado sem duplicar documents, downloads gestão/Balcão/biblioteca e view PDF bytes/MIME/CSP, publicação separada e adulteração404. ClamDQueueWorkerIntegrationTest verifica worker database. Outros testes usam fixtures/mock ou schema compatibility, identificados separadamente. Estes ensaios não são sessões novas do navegador nem renderização visual. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente.",parcial,"Percurso visual completo com reutilização pendente | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Nenhuma decisão; referências por ID e consentimento existentes | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-DESK-02: Título corrigido conservado; não copiar pedido/conta; outra conta negada | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-DESK-02: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-DESK-02,1,"[{""id"":""AUD-DESK-02"",""pedido"":""Reutilizar investimento, percurso, pedido e responsável no Balcão"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Título corrigido conservado; não copiar pedido/conta; outra conta negada | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Balcão/orientação""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa."," | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente."," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-CRM-01,Converter e acompanhar internamente com responsável/próxima ação,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",CRM/solicitações,/management/interests; /management/crm/leads; /management/crm/leads/{lead},"CrmController; ConvertInterestToLead; Lead/CrmTask | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","interest_requests: 4; leads: 0; investors: 3 | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","QA CRM/Portfolio e GET por gestor | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Tarefas existentes aceites, atribuídas e concluídas por responsável distinto; tarefa independente avança enquanto terra aguarda. Nenhuma transmissão externa. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente.",parcial,"Ativo: 0 leads e 0 negociações; operação real não demonstrada | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Responsáveis existentes; SuiteCRM externo é independente e desligado | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-CRM-01: Converter sem duplicar investidor; responsável autorizado; próxima tarefa antes de encerrar última | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-CRM-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-CRM-01,1,"[{""id"":""AUD-CRM-01"",""pedido"":""Converter e acompanhar internamente com responsável/próxima ação"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Converter sem duplicar investidor; responsável autorizado; próxima tarefa antes de encerrar última | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""CRM/solicitações""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa."," | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente."," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-GUIDE-01,Orientação explicável e evidência com âmbito/período,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",Balcão/orientação,/balcao-virtual/dossiers/{id}/orientacao,"InvestorGuidance; InvestorGuidanceRules; evidência por hash | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","desk_cases: 1; desk_requests: 0; desk_institutional_links: 0; desk_messages: 0 | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","QA regras e InvestorGuidanceTest | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Definição imutável v1/19 etapas/5 fases, pin na instância, triestado e dependências por ação; fases de outros roteiros preservadas. Informação/legalidade externa desconhecida não vira dispensa nem score. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente.",parcial,"Consistência e fontes por serviço ainda têm lacunas concretas | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Unidade/período/moeda declarados; IA externa não obrigatória | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-GUIDE-01: Mostrar contradição/lacuna sem bloquear preparação; evidência aplicável com autoria/data; não homologar | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-GUIDE-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-GUIDE-01,1,"[{""id"":""AUD-GUIDE-01"",""pedido"":""Orientação explicável e evidência com âmbito/período"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Mostrar contradição/lacuna sem bloquear preparação; evidência aplicável com autoria/data; não homologar | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Balcão/orientação""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa."," | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente."," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-GUIDE-01,Orientação explicável e evidência com âmbito/período,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",Balcão/orientação,/balcao-virtual/dossiers/{id}/orientacao,"InvestorGuidance; InvestorGuidanceRules; evidência por hash | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","desk_cases: 1; desk_requests: 0; desk_institutional_links: 0; desk_messages: 0 | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","QA regras e InvestorGuidanceTest | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Definição imutável v1/19 etapas/5 fases, pin na instância, triestado e dependências por ação; fases de outros roteiros preservadas. Informação/legalidade externa desconhecida não vira dispensa nem score. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente. | [Semântica QA 10/10/2026] Provasdeledger/colunas/definição:dashboard-active-readonly.json e opportunity-semantic-environment-qa.json;preservação18coleções/MFA18/manifestoativo:profiles-v1-preservation-qa.json.",parcial,"Consistência e fontes por serviço ainda têm lacunas concretas | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Unidade/período/moeda declarados; IA externa não obrigatória | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente. | [Semântica QA 10/10/2026] Leitura ativaREADONLY10/10:020000eBalcão07/190000+08/120000instalados;030000não;040000não;09/190000prepare_investor_pathausente(ledger/2colunas/definição). QA03/04/09-190instalados;definição19etapaspublicada61000919-0000-4000-8000-000000000001 SHAe0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf. 09/190000nãofoi substituída:continuanecessária paraativo e não se repeteQA. 030/040semdependênciaDDL190;190dependeBalcão/journeys/steps/questionnaire_versions;workflowusa020+030+040+tasks/catalogue. Planofuturo:visual/candidata→backup/restaurofrescos→códigoflagsfalse→030autenticada→040instalador/bootstrapautenticadosaindaemfalta→190apenasfaltantesvia/management/balcao-install→dadosreais/perfis→cartografiaprivadaidempotente→flagspercurso/oportunidades→publicaçãoseparada. 0fixturesQAnoativo;readytrueépreparação;semativaçãoautorizada;reversãodesativaflags/preservahistóricoourestaurabackupverificado,nãodropusado.","AUD-GUIDE-01: Mostrar contradição/lacuna sem bloquear preparação; evidência aplicável com autoria/data; não homologar | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-GUIDE-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-GUIDE-01,1,"[{""id"":""AUD-GUIDE-01"",""pedido"":""Orientação explicável e evidência com âmbito/período"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Mostrar contradição/lacuna sem bloquear preparação; evidência aplicável com autoria/data; não homologar | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Balcão/orientação""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa."," | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente."," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-SIM-01,Rascunhos do simulador e recuperação privada,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26. | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",simuladores,/simulador-fiscal; APIs de simulation-form-drafts,"SimulationFormDraft; SimulationForm; storage cifrado | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","simulation_form_drafts: 22; simulation_scenarios: 16; simulations: 16; simulation_tax_rules: ausente | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","PortalAuditContinuationTest: 5 testes / 203 asserções; phpunit-followup-recovery-final.log; API/Inertia/persistência demonstradas, browser indisponível; SimulationFormDraftTest; SimulationDraftContinuityTest | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; C25: criação/recuperação por dossier, bloqueio de contaminação de contexto, armazenamento local por contexto/draft e acesso privado independente; dois investimentos da mesma conta em QA. Rascunho anónimo e URLs diretas preservados. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente.",parcial,"ISO PT/ZA e legado Portugal recuperados em rascunho privado; países do simulador deixaram de consultar apenas jurisdição Moçambique. Aceitação visual e outros campos continuam pendentes. | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Nenhuma ativação fiscal por rascunho/documento | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-SIM-01: Guardar privado no servidor; nova sessão recupera; anónimo não envia PII; 422 conserva campos | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-SIM-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-SIM-01,1,"[{""id"":""AUD-SIM-01"",""pedido"":""Rascunhos do simulador e recuperação privada"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26."",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Guardar privado no servidor; nova sessão recupera; anónimo não envia PII; 422 conserva campos | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""simuladores""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.,"POST/PUT/GET simulation-drafts; países PT/ZA, ZZ 422; If-Match | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas. | C24: orientação fornece draft ID autorizado; recuperação por ID e conta indevida negada. | Fortify enable/confirm/login/MFA/logout e negativas de desencriptação verificadas no mesmo servidor18097. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas.","Snapshots privados cifrados; texto Portugal preservado; nenhuma execução fiscal | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa.","GET proprietário recupera ISO/lista e legado; outra conta 404 | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente. | Dois drafts sintéticos do dono não mudam o draft associado; GET conserva a ideia ligada. | Recuperação no servidor QA real após logout401 e login com sessão/cookies novos, não apenas actingAs/flushSession. A: necessidade0; B:70000; ambos20 unidades previstas pelas fórmulas existentes, desenho visual pendente. | CenárioA próprio recuperado após nova sessão HTTP com MFA confirmado. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente.","JSON de recuperação demonstrado; formulário renderizado pendente | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente. | Link preparado para o draft correto; clique/renderização pendentes.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-SIM-02,Cálculos financeiros e fiscais separados e rastreáveis,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26.",simuladores,/simulador-fiscal; /api/v1/simulations,"SimulationExecution; SimulationTaxParameterResolver; regras aprovadas | InvestorPath/InvestorPathDefinition, InvestorPathController, /investimentos e painel; entidades existentes, flag e definição versionada. Sem conversão dos roteiros antigos.","simulation_form_drafts: 22; simulation_scenarios: 16; simulations: 16; simulation_tax_rules: ausente | Runtime ativo READ ONLY 19:03:32UTC: extensão do percurso ausente, journey_steps=0; QA restaurada tem5 instâncias/95 etapas. Nenhuma ativação ativa autorizada.","QA SimulationExecutionTest; SimulationTaxRuleGovernanceTest; testes frontend | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; C26: reversão recusa segunda definição publicada antes de alterar RLS. Resultados locais reutilizam fórmulas existentes com snapshot/versionamento; não são simulação fiscal nem score/decisão externa. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | investor-path-recovered-calculations.json: cálculo pela função efetiva do dossier a partir dos snapshots realmente recuperados na nova sessão HTTP; A20unidades/0.00, B20/70000.00. C29: fixture HTTP inicial tinha orçamento vazio incompatível; criada revisão válida, resultados anteriores preservados e incompatibilidade não vira zero. Interface pendente.",parcial,"Cobertura jurídica por diploma/artigo e parâmetros concretos pendente | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Conferir período/alterações/âmbito na fonte oficial aceite; nunca substituir por zero ou taxa mais recente | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-SIM-02: Totais e fluxo reconcilam; parâmetro ausente indeterminado; períodos/versões distintos | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P1,AUD-SIM-02: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-SIM-02,1,"[{""id"":""AUD-SIM-02"",""pedido"":""Cálculos financeiros e fiscais separados e rastreáveis"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Aprovação expressa da execução I1–I3 exclusivamente QA; execução 09/10/2026, execucao-percurso-i1-i3.md, C25/C26.""],""aceitacao"":""Totais e fluxo reconcilam; parâmetro ausente indeterminado; períodos/versões distintos | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""simuladores""}]", | Interface integrada preparada /investimentos; props Inertia/build não demonstram clique/renderização A/B.," | POST /investimentos, aplicabilidade/etapas/resultados/tarefas e drafts por context; GET por ID/conta; permissões e versões ensaiadas."," | QA loopback55441: dossier/instância/19 etapas, payloads cifrados, resultados versionados, tasks/eventos; sem escrita ativa.", | A/B mesma conta e sessão HTTP limpa; GET recupera contexto próprio. Sessão nova no navegador ainda pendente.," | Evidência congelada recuperada, 20 unidades/70.000,00 pelas fórmulas existentes em teste frontend; decisão externa nunca inferida. Apresentação visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-LIB-01,Inventariar e consultar todo o acervo autorizado,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",biblioteca,/documentos; /legislacao; /management/portal-services,PortalServicesController; documents/portal_resources; inventário privado,documents: 4; portal_resources: 4; portal_resource_links: 19,"Inventário atual; QA biblioteca; leitura ativa 4 documentos | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Acrescentado somente o DOCX solicitado e seu fluxograma à inventariação existente; leitura integral e SHA256. Consulta/estado documental/cálculo independentes; aceitação oficial preservada. | C35: campos data/emissor opcionais omitidos causavam500; corrigidos sem inventar dados. C36: original cifrado clean devolvia404 em consumidores por comparar ciphertext ao hash original; VerifiedDocumentBinary partilhado recupera bytes verificados, mantendo permissões/cifra. document-consumers-real-qa.xml: PortalRealDocumentConsumersTest (ClamD real) verifica biblioteca privada→scan→classificação→publicação separada→download,409versão/dedup/404hash/403gestão, Balcão upload→scan→download/dedup/confidential/403estranho, reutilização do original cifrado sem duplicar documents, downloads gestão/Balcão/biblioteca e view PDF bytes/MIME/CSP, publicação separada e adulteração404. ClamDQueueWorkerIntegrationTest verifica worker database. Outros testes usam fixtures/mock ou schema compatibility, identificados separadamente. Estes ensaios não são sessões novas do navegador nem renderização visual.",parcial,"253 ficheiros externos + 60 anexos embebidos inventariados não equivalem a biblioteca publicada completa | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Autorização por ficheiro; bloquear apenas impedimento concreto | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-LIB-01: Disponibilidade/documentação/uso em cálculo separados; publicação não exige relação a módulo | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P1,AUD-LIB-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LIB-01,1,"[{""id"":""AUD-LIB-01"",""pedido"":""Inventariar e consultar todo o acervo autorizado"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Disponibilidade/documentação/uso em cálculo separados; publicação não exige relação a módulo | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-LIB-02,Importação privada em lote idempotente com pré-visualização,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",biblioteca,Comandos e gestão da biblioteca,documents; checksum; scan; auditoria existentes,documents: 4; portal_resources: 4; portal_resource_links: 19,QA biblioteca/scan; inventário com hash,parcial,Cobertura de importação de todos os ficheiros/anexos ainda pendente,Manifesto de divulgação e impedimentos por ficheiro; sem nova certificação da fonte,AUD-LIB-02: Hash/dedup bytes/conflito identidade/versão; escrita privada; scan; nunca publicar lote automaticamente,P1,AUD-LIB-02: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LIB-02,1,"[{""id"":""AUD-LIB-02"",""pedido"":""Importação privada em lote idempotente com pré-visualização"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Hash/dedup bytes/conflito identidade/versão; escrita privada; scan; nunca publicar lote automaticamente"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-SCAN-01,Scanner ClamD real e derivados seguros,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",biblioteca,malware:health; recursos/downloads,MalwareScanner; ScanDocumentForMalware; OpportunityImageProcessor,documents: 4; portal_resources: 4; portal_resource_links: 19,"clamd-lote2.json; clamd-lote2-tests.log: seis testes reais/29 asserções; ClamAV 1.5.4 em loopback, assinaturas 2026-10-09T08:25:40Z, EICAR detetado em memória; worker QA guarda clean/hash sem publicar | C31 corrigiu RouteNotFoundException nos previews de derivadas (management.opportunity-image-preview), sem alterar URLs. resources-real-http-qa.json/document-real-persistence-qa.json: PHP web QA com GD; PDF/PNG e3WebP cifrados/restricted, cinco scans ClamAV1.5.4 clean/hash próprios; três downloads assinados reais, assinatura ausente403 e conta comum403. OpportunityRealDocumentOperationsTest: quarentena423, indisponível/inconclusivo, retry real, substituição preserva original,409versão, exclusão/restauro, adulteração409. OpportunityResourcesTest usa scanner fixture: não é prova real. | C35: campos data/emissor opcionais omitidos causavam500; corrigidos sem inventar dados. C36: original cifrado clean devolvia404 em consumidores por comparar ciphertext ao hash original; VerifiedDocumentBinary partilhado recupera bytes verificados, mantendo permissões/cifra. document-consumers-real-qa.xml: PortalRealDocumentConsumersTest (ClamD real) verifica biblioteca privada→scan→classificação→publicação separada→download,409versão/dedup/404hash/403gestão, Balcão upload→scan→download/dedup/confidential/403estranho, reutilização do original cifrado sem duplicar documents, downloads gestão/Balcão/biblioteca e view PDF bytes/MIME/CSP, publicação separada e adulteração404. ClamDQueueWorkerIntegrationTest verifica worker database. Outros testes usam fixtures/mock ou schema compatibility, identificados separadamente. Estes ensaios não são sessões novas do navegador nem renderização visual.",parcial,"UI documental e derivadas ainda não observadas; operações de biblioteca/Balcão não são encerradas pelos ensaios de oportunidades. Há ensaios reais específicos suplementares, sem fecho de PDF preview/lotes/tipos/perfis/partilhas. Arranque após reboot/manutenção de assinaturas e GD/WebP no PHP ativo não verificados. Nenhuma publicação ativa nem cálculo.","Daemon/assinaturas afetam scans/libertação de binários; GD/WebP afeta geração de derivadas. Não bloqueiam metadados, países, estatísticas nem preparação paralela. Fonte aceite não dispensa scan por bytes.",AUD-SCAN-01: Scanner disponível com versão/assinaturas; EICAR isolado; binário/hash limpo; scan próprio de derivada,P1,AUD-SCAN-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-SCAN-01,1,"[{""id"":""AUD-SCAN-01"",""pedido"":""Scanner ClamD real e derivados seguros"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Scanner disponível com versão/assinaturas; EICAR isolado; binário/hash limpo; scan próprio de derivada"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]",Estados de scan/derivadas preparados; UI pendente,"PING/VERSION/INSTREAM reais; EICAR FOUND; indisponibilidade/limites continuam inconclusive | Upload, geração, recuperação de previews e downloads pelo servidor QA18097; resultados concretos por ficheiro.","Fila database QA passa pending -> clean, hash registado; ficheiro permanece internal | Cinco documents cifrados e respectivos document_malware_scans reais, hashes próprios e classificação restricted.","documents/document_malware_scans recuperados pelo teste do worker; nenhuma publicação | Bytes originais e3WebP recuperados por HTTP, comparados com hashes; original anterior preservado na substituição e após exclusão lógica.",Scanner real saudável nesta sessão; não certifica manutenção após reboot ou web ativo,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-LIB-01,Inventariar e consultar todo o acervo autorizado,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",biblioteca,/documentos; /legislacao; /management/portal-services,PortalServicesController; documents/portal_resources; inventário privado,documents: 4; portal_resources: 4; portal_resource_links: 19,"Inventário atual; QA biblioteca; leitura ativa 4 documentos | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Acrescentado somente o DOCX solicitado e seu fluxograma à inventariação existente; leitura integral e SHA256. Consulta/estado documental/cálculo independentes; aceitação oficial preservada. | C35: campos data/emissor opcionais omitidos causavam500; corrigidos sem inventar dados. C36: original cifrado clean devolvia404 em consumidores por comparar ciphertext ao hash original; VerifiedDocumentBinary partilhado recupera bytes verificados, mantendo permissões/cifra. document-consumers-real-qa.xml: PortalRealDocumentConsumersTest (ClamD real) verifica biblioteca privada→scan→classificação→publicação separada→download,409versão/dedup/404hash/403gestão, Balcão upload→scan→download/dedup/confidential/403estranho, reutilização do original cifrado sem duplicar documents, downloads gestão/Balcão/biblioteca e view PDF bytes/MIME/CSP, publicação separada e adulteração404. ClamDQueueWorkerIntegrationTest verifica worker database. Outros testes usam fixtures/mock ou schema compatibility, identificados separadamente. Estes ensaios não são sessões novas do navegador nem renderização visual. | [QA independente 10/10/2026] C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal. C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas.",parcial,"Histórico até09/10 (preservado): 253 ficheiros externos + 60 anexos embebidos inventariados não equivalem a biblioteca publicada completa | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | [QA independente 10/10/2026] Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas.","Autorização por ficheiro; bloquear apenas impedimento concreto | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-LIB-01: Disponibilidade/documentação/uso em cálculo separados; publicação não exige relação a módulo | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P1,AUD-LIB-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LIB-01,1,"[{""id"":""AUD-LIB-01"",""pedido"":""Inventariar e consultar todo o acervo autorizado"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Disponibilidade/documentação/uso em cálculo separados; publicação não exige relação a módulo | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado.",Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-LIB-02,Importação privada em lote idempotente com pré-visualização,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",biblioteca,Comandos e gestão da biblioteca,documents; checksum; scan; auditoria existentes,documents: 4; portal_resources: 4; portal_resource_links: 19,"QA biblioteca/scan; inventário com hash | [QA independente 10/10/2026] C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal. C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas.",parcial,"Histórico até09/10 (preservado): Cobertura de importação de todos os ficheiros/anexos ainda pendente | [QA independente 10/10/2026] Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas.",Manifesto de divulgação e impedimentos por ficheiro; sem nova certificação da fonte,AUD-LIB-02: Hash/dedup bytes/conflito identidade/versão; escrita privada; scan; nunca publicar lote automaticamente,P1,AUD-LIB-02: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LIB-02,1,"[{""id"":""AUD-LIB-02"",""pedido"":""Importação privada em lote idempotente com pré-visualização"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Hash/dedup bytes/conflito identidade/versão; escrita privada; scan; nunca publicar lote automaticamente"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado.",Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-SCAN-01,Scanner ClamD real e derivados seguros,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",biblioteca,malware:health; recursos/downloads,"MalwareScanner; ScanDocumentForMalware; OpportunityImageProcessor | [Instalação/cartografia QA 10/10/2026] Seis originais fundiários/parceria possuem scan real ClamAV limpo, data de assinaturas e hash analisado igual ao original armazenado e recuperado por HTTP. Não foram alterados originais nem simulados scans.",documents: 4; portal_resources: 4; portal_resource_links: 19 | [Instalação/cartografia QA 10/10/2026] Este ensaio é exclusivamente QA; não inspecionou nem alterou documentos ou partilhas ativos.,"clamd-lote2.json; clamd-lote2-tests.log: seis testes reais/29 asserções; ClamAV 1.5.4 em loopback, assinaturas 2026-10-09T08:25:40Z, EICAR detetado em memória; worker QA guarda clean/hash sem publicar | C31 corrigiu RouteNotFoundException nos previews de derivadas (management.opportunity-image-preview), sem alterar URLs. resources-real-http-qa.json/document-real-persistence-qa.json: PHP web QA com GD; PDF/PNG e3WebP cifrados/restricted, cinco scans ClamAV1.5.4 clean/hash próprios; três downloads assinados reais, assinatura ausente403 e conta comum403. OpportunityRealDocumentOperationsTest: quarentena423, indisponível/inconclusivo, retry real, substituição preserva original,409versão, exclusão/restauro, adulteração409. OpportunityResourcesTest usa scanner fixture: não é prova real. | C35: campos data/emissor opcionais omitidos causavam500; corrigidos sem inventar dados. C36: original cifrado clean devolvia404 em consumidores por comparar ciphertext ao hash original; VerifiedDocumentBinary partilhado recupera bytes verificados, mantendo permissões/cifra. document-consumers-real-qa.xml: PortalRealDocumentConsumersTest (ClamD real) verifica biblioteca privada→scan→classificação→publicação separada→download,409versão/dedup/404hash/403gestão, Balcão upload→scan→download/dedup/confidential/403estranho, reutilização do original cifrado sem duplicar documents, downloads gestão/Balcão/biblioteca e view PDF bytes/MIME/CSP, publicação separada e adulteração404. ClamDQueueWorkerIntegrationTest verifica worker database. Outros testes usam fixtures/mock ou schema compatibility, identificados separadamente. Estes ensaios não são sessões novas do navegador nem renderização visual. | [QA independente 10/10/2026] C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal. C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas. | [Instalação/cartografia QA 10/10/2026] independent-documents-http-qa.json e independent-documents-verification-qa.json; servidor QA 18097, API/persistência demonstradas, interface não observada.",parcial,"Histórico até09/10 (preservado): UI documental e derivadas ainda não observadas; operações de biblioteca/Balcão não são encerradas pelos ensaios de oportunidades. Há ensaios reais específicos suplementares, sem fecho de PDF preview/lotes/tipos/perfis/partilhas. Arranque após reboot/manutenção de assinaturas e GD/WebP no PHP ativo não verificados. Nenhuma publicação ativa nem cálculo. | [QA independente 10/10/2026] Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas. | [Instalação/cartografia QA 10/10/2026] ClamD real demonstrado nestas operações; arranque operacional, PDFs gerados, novos tipos e derivadas não cobertos continuam pendentes por operação.","Daemon/assinaturas afetam scans/libertação de binários; GD/WebP afeta geração de derivadas. Não bloqueiam metadados, países, estatísticas nem preparação paralela. Fonte aceite não dispensa scan por bytes.",AUD-SCAN-01: Scanner disponível com versão/assinaturas; EICAR isolado; binário/hash limpo; scan próprio de derivada,P1,AUD-SCAN-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-SCAN-01,1,"[{""id"":""AUD-SCAN-01"",""pedido"":""Scanner ClamD real e derivados seguros"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Scanner disponível com versão/assinaturas; EICAR isolado; binário/hash limpo; scan próprio de derivada"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""biblioteca""}]","Estados de scan/derivadas preparados; UI pendente | [QA independente 10/10/2026] Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote. | [Instalação/cartografia QA 10/10/2026] Modelo Inertia de impressão recuperado; nenhum clique, mapa ou PDF de navegador observado.","PING/VERSION/INSTREAM reais; EICAR FOUND; indisponibilidade/limites continuam inconclusive | Upload, geração, recuperação de previews e downloads pelo servidor QA18097; resultados concretos por ficheiro. | [QA independente 10/10/2026] Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota. | [Instalação/cartografia QA 10/10/2026] Rotas reais de terra-duat e parcerias/salas; sessões Fortify, verificações permitidas/negadas e cabeçalho do alvo QA antes de escrever.","Fila database QA passa pending -> clean, hash registado; ficheiro permanece internal | Cinco documents cifrados e respectivos document_malware_scans reais, hashes próprios e classificação restricted. | [QA independente 10/10/2026] size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado. | [Instalação/cartografia QA 10/10/2026] Três originais por consumidor e eventos de partilha persistidos exclusivamente na base QA isolada.","documents/document_malware_scans recuperados pelo teste do worker; nenhuma publicação | Bytes originais e3WebP recuperados por HTTP, comparados com hashes; original anterior preservado na substituição e após exclusão lógica. | [QA independente 10/10/2026] VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado. | [Instalação/cartografia QA 10/10/2026] Nova sessão MFA recupera os mesmos hashes; revogação mantém os originais e remove o acesso do candidato.","Scanner real saudável nesta sessão; não certifica manutenção após reboot ou web ativo | [QA independente 10/10/2026] Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes. | [Instalação/cartografia QA 10/10/2026] JSON, modelo de impressão e binários demonstrados; resultado visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-EDU-01,Educação: investimento e procura/capacidade com rascunhos por ator,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",educação,/educacao; /management/education; APIs skills-edu,EducationController; EducationInvestmentController; schema skills_edu existente,labour_demands: 0; training_capacities: 0; education_opportunities: 0; education_investment_proposals: 0,QA EducationTest/SkillsEducationSchemaTest; GETs; schema skills_edu ativo vazio,parcial,Fluxos completos por ator e dados institucionais não demonstrados; não confundir catálogo e submódulo,Reutilizar entidades e configurações existentes; mandatos só para atos institucionais,AUD-EDU-01: Criar/editar/recuperar; distinguir vagas/trabalhadores; acesso e fonte; sem autoacreditação,P1,AUD-EDU-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-EDU-01,1,"[{""id"":""AUD-EDU-01"",""pedido"":""Educação: investimento e procura/capacidade com rascunhos por ator"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Criar/editar/recuperar; distinguir vagas/trabalhadores; acesso e fonte; sem autoacreditação"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""educação""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-PART-01,"Bolsa: rascunhos, candidaturas, sala e marcos","Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",Bolsa/parcerias,/parcerias; /parcerias/{id}; sala,PartnershipExchange; portal_partnerships; messages/rooms,portal_partnerships: 0; partnership_rooms: 0; partnership_interests: 0,"QA PartnershipExchangeTest; instalação ativa confirmada | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; S12–S15 propostos reutilizam parceiros/sala/marcos/documentos; aprovação, condições e desembolso são atos distintos. Não criar financiamento paralelo ou integração bancária fictícia.",parcial,"Cadastro ativo vazio; percurso real e acordos externos ausentes | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Reutilizar conta/organização/documento; acordo não é assinatura certificada | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-PART-01: Consentimento, versões, candidatura isolada, retiro, mensagens, acordo/marcos com papéis reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P2,AUD-PART-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-PART-01,1,"[{""id"":""AUD-PART-01"",""pedido"":""Bolsa: rascunhos, candidaturas, sala e marcos"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Consentimento, versões, candidatura isolada, retiro, mensagens, acordo/marcos com papéis reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Bolsa/parcerias""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-PART-01,"Bolsa: rascunhos, candidaturas, sala e marcos","Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",Bolsa/parcerias,/parcerias; /parcerias/{id}; sala,"PartnershipExchange; portal_partnerships; messages/rooms | [Instalação/cartografia QA 10/10/2026] Sala QA1: PDF, PNG e JPEG privados do autor; candidato recebe 404 e não pode alterar partilha (403). Partilha explícita permite recuperar bytes noutra sessão MFA; revogação retira listagem e download (404), mantendo original do autor. Gestor não participante e organização alheia recebem 403; seis transições de partilha auditadas.",portal_partnerships: 0; partnership_rooms: 0; partnership_interests: 0 | [Instalação/cartografia QA 10/10/2026] Este ensaio é exclusivamente QA; não inspecionou nem alterou documentos ou partilhas ativos.,"QA PartnershipExchangeTest; instalação ativa confirmada | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; S12–S15 propostos reutilizam parceiros/sala/marcos/documentos; aprovação, condições e desembolso são atos distintos. Não criar financiamento paralelo ou integração bancária fictícia. | [QA independente 10/10/2026] C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal. C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas. | [Instalação/cartografia QA 10/10/2026] independent-documents-http-qa.json e independent-documents-verification-qa.json; servidor QA 18097, API/persistência demonstradas, interface não observada.",parcial,"Histórico até09/10 (preservado): Cadastro ativo vazio; percurso real e acordos externos ausentes | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | [QA independente 10/10/2026] Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas. | [Instalação/cartografia QA 10/10/2026] Resultado visual, impressão/exportações e restantes ações da bolsa continuam com critérios próprios pendentes.","Reutilizar conta/organização/documento; acordo não é assinatura certificada | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-PART-01: Consentimento, versões, candidatura isolada, retiro, mensagens, acordo/marcos com papéis reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P2,AUD-PART-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-PART-01,1,"[{""id"":""AUD-PART-01"",""pedido"":""Bolsa: rascunhos, candidaturas, sala e marcos"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Consentimento, versões, candidatura isolada, retiro, mensagens, acordo/marcos com papéis reais | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""Bolsa/parcerias""}]","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote. | [Instalação/cartografia QA 10/10/2026] Modelo Inertia de impressão recuperado; nenhum clique, mapa ou PDF de navegador observado.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota. | [Instalação/cartografia QA 10/10/2026] Rotas reais de terra-duat e parcerias/salas; sessões Fortify, verificações permitidas/negadas e cabeçalho do alvo QA antes de escrever.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado. | [Instalação/cartografia QA 10/10/2026] Três originais por consumidor e eventos de partilha persistidos exclusivamente na base QA isolada.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado. | [Instalação/cartografia QA 10/10/2026] Nova sessão MFA recupera os mesmos hashes; revogação mantém os originais e remove o acesso do candidato.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes. | [Instalação/cartografia QA 10/10/2026] JSON, modelo de impressão e binários demonstrados; resultado visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-BIZ-01,"Negócios existentes, direitos/mandatos e publicação","Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",negócios,/negocios; /investidor/negocios; /management/negocios,ExistingBusiness; revisions; documents; policy MFA,existing_businesses: 2; existing_business_revisions: 2,QA ExistingBusiness e GETs com MFA; ativo 2 negócios,parcial,Direitos/mandatos/documentos concretos vazios; UI integral pendente,Mandatos e dados jurídicos do objeto; nenhuma aprovação institucional inferida,AUD-BIZ-01: Guardar/recuperar/conflito; revisar por ator designado; público omite privados,P2,AUD-BIZ-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-BIZ-01,1,"[{""id"":""AUD-BIZ-01"",""pedido"":""Negócios existentes, direitos/mandatos e publicação"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Guardar/recuperar/conflito; revisar por ator designado; público omite privados"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""negócios""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-LAND-01,Assistência fundiária sem venda automática de direito,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",oportunidades,/terra-duat; /investidor/terra-duat; /management/terra-duat,LandAssistanceController; documents; geo_locations,opportunities: 6; opportunity_images: ausente; opportunity_documents: ausente; opportunity_location_drafts: ausente,"QA LandAssistance; rastreabilidade documental | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; S09–S11 propostos usam assistência fundiária e evidências atuais. Ausência declarada de terra dispensa preparação do ramo, não inventa dispensa legal. Vínculo ao contexto e ato jurídico ainda incompletos.",parcial,"Percurso visual integral e dados concretos pendentes | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Objetos/direitos identificados; sem inferir legitimidade por fonte genérica | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-LAND-01: Rascunho incompleto; fonte/estado jurídico separado; escopo e transições verificáveis | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P2,AUD-LAND-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LAND-01,1,"[{""id"":""AUD-LAND-01"",""pedido"":""Assistência fundiária sem venda automática de direito"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Rascunho incompleto; fonte/estado jurídico separado; escopo e transições verificáveis | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""oportunidades""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-OPS-01,Instalação consolidada com backup/restauro e hash atual,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas",governação/outros,/management/opportunity-resources-install,OpportunityResourceInstallation; desk-activation-backup,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,"Backup/restauro 2026-10-09T17:47:35+00:00; desk_restore_20261009_174726_test:55441; 288 tabelas e cinco ficheiros; compatibilidade/reversão QA do código atual | C28: preparador sem contagem381 fixa; provas/autenticação/hashes/compatibilidade conservados. Preview HTTP da QA: pathInstalled=true, pathQaVerified=false; fingerprint inclui consumidores C27. Backup final após UI ainda não renovado; nenhuma instalação ativa. | C30 mecanismos autenticados demonstrados em QA; plano-ativacao.md distingue código, instalações ausentes, flag e cartografia. Ready anterior não significa instalação/conclusão.",parcial,"Recursos030000 e percurso190000 ausentes no último retrato ativo; prévia ativa futura deve reconfirmar ledger. Mecanismo cartográfico C30 demonstrado em QA; disponível somente aí, e no ativo exige prova específica vinculada ao alvo/revisão/backup/restauro/UI. Revisão candidata não fixada: resultados manuais A/B e consumidores pendentes; backup final não renovado. Publicação é ação separada, não fornecida pelo importador.",A/B e consumidores na interface → backup/restauro/compatibilidade da revisão final → preview e ações autenticadas de instalações ausentes → flag separada; cartografia privada/divulgação separadas. Ativo fora da autorização atual.,AUD-OPS-01: Prova do código/destino atual; 288 tabelas/5 ficheiros restaurados; up/down QA; ação autenticada única,P0,AUD-OPS-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-OPS-01,1,"[{""id"":""AUD-OPS-01"",""pedido"":""Instalação consolidada com backup/restauro e hash atual"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas""],""aceitacao"":""Prova do código/destino atual; 288 tabelas/5 ficheiros restaurados; up/down QA; ação autenticada única"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-LAND-01,Assistência fundiária sem venda automática de direito,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",oportunidades,/terra-duat; /investidor/terra-duat; /management/terra-duat,"LandAssistanceController; documents; geo_locations | [Instalação/cartografia QA 10/10/2026] PDF, PNG e JPEG sintéticos: upload pelo servidor QA, scan ClamD real, original recuperado pelo autor QA21 noutra sessão MFA. Gestor QA14 e outro investidor QA23 recebem 404 no percurso privado. País MZ e origem PT persistidos e recuperados. Modelo de impressão responde com aviso de ausência de decisão externa.",opportunities: 6; opportunity_images: ausente; opportunity_documents: ausente; opportunity_location_drafts: ausente | [Instalação/cartografia QA 10/10/2026] Este ensaio é exclusivamente QA; não inspecionou nem alterou documentos ou partilhas ativos.,"QA LandAssistance; rastreabilidade documental | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; S09–S11 propostos usam assistência fundiária e evidências atuais. Ausência declarada de terra dispensa preparação do ramo, não inventa dispensa legal. Vínculo ao contexto e ato jurídico ainda incompletos. | [QA independente 10/10/2026] C39: document-independent-before-qa.xml reproduz404 dos originais canónicos cifrados no fundiário e na sala de parceria. document-independent-qa.xml: PDF/PNG/JPEG, scan ClamD real, quarentena, autorização, download cifrado/bytes originais, tamper404, recuperação; partilha autor→candidato, outro perfil403, revogação→404 e eventos persistidos. document-batch-independent-qa.xml: caso real de importação privada/dedup/replay/conflito de identidade/original hash/scan/download/perfis; dois casos antigos são fixtures/queue mock, não prova ClamD. C40: CLI --actor é atribuição, não autenticação; apply recusa ambiente ativo e ator QA sem manage-portal. C41: document-types-fixture-qa.json comprova PDFs sintéticos válidos de1página nos novos testes; resources-real-http-qa.json renova upload/scan real/recuperação de um novo PDF válido no servidor18097, sem substituir antigos; resource-originals-preservation-http-qa.json recupera os5binários anteriores com mesmo SHA, e parseia o novo PDF recuperado. PNG/3WebP anteriores recuperados com assinatura/perfis, sem afirmar novos scans das derivadas. C42: passwords de2atores auxiliaresQA rodadas/remember tokens revogados; MFA e conta18 preservados; nenhum segredo exportado nas novas provas. | [Instalação/cartografia QA 10/10/2026] independent-documents-http-qa.json e independent-documents-verification-qa.json; servidor QA 18097, API/persistência demonstradas, interface não observada.",parcial,"Histórico até09/10 (preservado): Percurso visual integral e dados concretos pendentes | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | [QA independente 10/10/2026] Correções de recuperação cifrada em fundiário/parcerias e lote QA demonstradas por rotas/kernel+DB; não são sessão/browser18097. Continuam renderização PDF/impressão, ações visuais e consumidores/tipos restantes, aplicação de lote por mecanismo ativo autenticado, manutenção/arranque permanente ClamD e GD do PHP ativo. Provas WebP/biblioteca/Balcão anteriores conservadas, não repetidas nem generalizadas. | [Instalação/cartografia QA 10/10/2026] Aspeto da interface e PDF gerado pelo navegador pendentes; não demonstra todos os perfis, filtros, estatísticas ou todos os campos fundiários.","Objetos/direitos identificados; sem inferir legitimidade por fonte genérica | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-LAND-01: Rascunho incompleto; fonte/estado jurídico separado; escopo e transições verificáveis | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P2,AUD-LAND-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-LAND-01,1,"[{""id"":""AUD-LAND-01"",""pedido"":""Assistência fundiária sem venda automática de direito"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Rascunho incompleto; fonte/estado jurídico separado; escopo e transições verificáveis | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""oportunidades""}]","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Sem prova visual de leitura PDF, impressão, partilha ou derivadas neste lote. | [Instalação/cartografia QA 10/10/2026] Modelo Inertia de impressão recuperado; nenhum clique, mapa ou PDF de navegador observado.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Fundiário: owner200, outro404; parceria: autor200, candidato só após partilha200, gestor/estranho403, revogada404. Quarentena/tamper404 conforme rota. | [Instalação/cartografia QA 10/10/2026] Rotas reais de terra-duat e parcerias/salas; sessões Fortify, verificações permitidas/negadas e cabeçalho do alvo QA antes de escrever.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] size_bytes/uploaded_by preenchidos em novos uploads; partilhas/revogação/leituras auditadas; originais privados e hash preservados, nenhum dado ativo alterado. | [Instalação/cartografia QA 10/10/2026] Três originais por consumidor e eventos de partilha persistidos exclusivamente na base QA isolada.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] VerifiedDocumentBinary comum decifra e verifica original sem cópia pública; GET com novo contexto de ator recupera estado/permissão. Impressão devolve props200, não PDF renderizado. | [Instalação/cartografia QA 10/10/2026] Nova sessão MFA recupera os mesmos hashes; revogação mantém os originais e remove o acesso do candidato.","Não demonstrado individualmente; localizar critério e executar em QA. | [QA independente 10/10/2026] Bytes PDF/PNG/JPEG comparados ao original; estado de partilha recuperado. Interface/PDF visual continuam pendentes. | [Instalação/cartografia QA 10/10/2026] JSON, modelo de impressão e binários demonstrados; resultado visual pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-OPS-01,Instalação consolidada com backup/restauro e hash atual,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas",governação/outros,/management/opportunity-resources-install,OpportunityResourceInstallation; desk-activation-backup | [Perfis v1 QA10/10/2026] Reutilização/permissões organizacionais e workflow parcial nos AUD-PROFILE-01–32; nenhum sistema paralelo de identidades. | [Instalação/cartografia QA 10/10/2026] 030→040→190 preservada:030/040/09-190 QA instaladas e ausentes no ativo lido READONLY. GET/POST/management/profile-install disponíveisQA; preparação não instala nem disponibiliza o percurso.,"Requisito transversal; estado/configuração e snapshots descritos no relatório executivo | [Instalação/cartografia QA 10/10/2026] AtivoREADONLY:030/040/09-190ausentes,0geometrias,flagsfalse/manifestopreservado; não ativado.","Backup/restauro 2026-10-09T17:47:35+00:00; desk_restore_20261009_174726_test:55441; 288 tabelas e cinco ficheiros; compatibilidade/reversão QA do código atual | C28: preparador sem contagem381 fixa; provas/autenticação/hashes/compatibilidade conservados. Preview HTTP da QA: pathInstalled=true, pathQaVerified=false; fingerprint inclui consumidores C27. Backup final após UI ainda não renovado; nenhuma instalação ativa. | C30 mecanismos autenticados demonstrados em QA; plano-ativacao.md distingue código, instalações ausentes, flag e cartografia. Ready anterior não significa instalação/conclusão. | [QA independente 10/10/2026] Lote independente: geo32novas/393privadas/replay/reversão com dependências; docs/lote QA/perfis. Fingerprints atuais em investor-path-qa-runtime.json; plano-ativacao.md reconciliado. Ready anterior histórico; candidata/ativação falsas. | [QA dashboard 10/10/2026] dashboard-active-readonly.json reconfirma020000 instalada e030000 ausente,0 escrita ativa;build QA separado,manifesto ativo preservado. Fingerprints incluem dashboard/sidebar/middleware/config/schema/adaptador; evidência anterior ready não certifica esta revisão. | [Perfis v1 QA10/10/2026] Dashboard→novo draft15→recuperaçãoMFA→coedição21/22 HTTP; tipos/org/multirrole403; requestArchive persiste. Submissão422 por contrato completo ausente. VisualC37/C43/A-B pendente. | [Semântica QA 10/10/2026] Provasdeledger/colunas/definição:dashboard-active-readonly.json e opportunity-semantic-environment-qa.json;preservação18coleções/MFA18/manifestoativo:profiles-v1-preservation-qa.json. | [Instalação/cartografia QA 10/10/2026] profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.",parcial,"Histórico até09/10 (preservado): Recursos030000 e percurso190000 ausentes no último retrato ativo; prévia ativa futura deve reconfirmar ledger. Mecanismo cartográfico C30 demonstrado em QA; disponível somente aí, e no ativo exige prova específica vinculada ao alvo/revisão/backup/restauro/UI. Revisão candidata não fixada: resultados manuais A/B e consumidores pendentes; backup final não renovado. Publicação é ação separada, não fornecida pelo importador. | [QA independente 10/10/2026] C37/A/B/consumidores visuais pendentes; renovar backup/restauro/compatibilidade da candidata final. Ativo não consultado novamente nem alterado; contagens/ledger ativos têm de ser reconfirmados antes de qualquer ação futura. | [QA dashboard 10/10/2026] Revisão candidata não fixada: C37/C43/A-B/consumidores visuais pendentes. Renovar backup/restauro depois desses ensaios. Ativação de atalhos/arquivo e adaptador especializado separada das instalações030000/190000/importação1→2→3/publicação. | [Perfis v1 QA10/10/2026] Critérios específicos preservados; não confundir workflow parcial/props de menu com submissão/aprovação/publicação completas ou demonstração visual. | [Instalação/cartografia QA 10/10/2026] Candidata não fixada; visualC37/QA21/A-B, prova ativa de backup/restauro e autorização de ativação futura; não aplicar ativos nesta autorização.","Histórico até09/10 (preservado): A/B e consumidores na interface → backup/restauro/compatibilidade da revisão final → preview e ações autenticadas de instalações ausentes → flag separada; cartografia privada/divulgação separadas. Ativo fora da autorização atual. | [QA independente 10/10/2026] Recursos030000 se ausentes→percurso190000 se pendente→flag separada. Importação GIS1→2→3 privada; publicação separada; lote documental ativo requer mecanismo autenticado. Nenhum CLI QA pode aplicar no ativo. | [Semântica QA 10/10/2026] Leitura ativaREADONLY10/10:020000eBalcão07/190000+08/120000instalados;030000não;040000não;09/190000prepare_investor_pathausente(ledger/2colunas/definição). QA03/04/09-190instalados;definição19etapaspublicada61000919-0000-4000-8000-000000000001 SHAe0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf. 09/190000nãofoi substituída:continuanecessária paraativo e não se repeteQA. 030/040semdependênciaDDL190;190dependeBalcão/journeys/steps/questionnaire_versions;workflowusa020+030+040+tasks/catalogue. Planofuturo:visual/candidata→backup/restaurofrescos→códigoflagsfalse→030autenticada→040instalador/bootstrapautenticadosaindaemfalta→190apenasfaltantesvia/management/balcao-install→dadosreais/perfis→cartografiaprivadaidempotente→flagspercurso/oportunidades→publicaçãoseparada. 0fixturesQAnoativo;readytrueépreparação;semativaçãoautorizada;reversãodesativaflags/preservahistóricoourestaurabackupverificado,nãodropusado.",AUD-OPS-01: Prova do código/destino atual; 288 tabelas/5 ficheiros restaurados; up/down QA; ação autenticada única,P0,AUD-OPS-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-OPS-01,1,"[{""id"":""AUD-OPS-01"",""pedido"":""Instalação consolidada com backup/restauro e hash atual"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas""],""aceitacao"":""Prova do código/destino atual; 288 tabelas/5 ficheiros restaurados; up/down QA; ação autenticada única"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA. | [Instalação/cartografia QA 10/10/2026] Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.,Não demonstrado individualmente; localizar critério e executar em QA. | [Instalação/cartografia QA 10/10/2026] HTTP 18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.,Não demonstrado individualmente; localizar critério e executar em QA. | [Instalação/cartografia QA 10/10/2026] Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:operação sem alterações DDL. Recursos/originais e15geometrias gravados somenteQA.,"Não demonstrado individualmente; localizar critério e executar em QA. | [Instalação/cartografia QA 10/10/2026] Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.",Não demonstrado individualmente; localizar critério e executar em QA. | [Instalação/cartografia QA 10/10/2026] JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.,"Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada | [Instalação/cartografia QA 10/10/2026] Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados."
AUD-OPS-02,Excluir execução simultânea de suites sobre a mesma QA,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",governação/outros,tests/TestCase.php,Guarda de alvo + flock por host/porta/base antes da migração,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,"Suite sequencial QA: 384/384 testes, 5215 asserções; skips0; guarda/lock preservados; path-regression-final.xml",concluído e demonstrado,Correção do tooling QA demonstrada; não é falha do portal nem aceitação funcional completa,Executável sem decisão humana; nenhum teste na base ativa,AUD-OPS-02: Segundo runner recusado antes de conexão/limpeza; suite sequencial passa; bases diferentes independentes,P0,AUD-OPS-02: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-OPS-02,1,"[{""id"":""AUD-OPS-02"",""pedido"":""Excluir execução simultânea de suites sobre a mesma QA"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Segundo runner recusado antes de conexão/limpeza; suite sequencial passa; bases diferentes independentes"",""estado"":""concluído e demonstrado"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]","Não aplicável: requisito operacional, sem interface de utilizador",Guarda/teste de identidade e READ ONLY demonstrados,Escrita exclusiva QA; zero escrita ativa por estas ferramentas,Backup/restauro e hashes comparados,"Lock concorrente recusado antes de limpeza; suite sequencial atual: 373 passaram, 3 ClamD saltados, 4608 asserções",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-OPS-03,Leitura ativa e ensaios QA preservam dados/histórico,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",governação/outros,tools/portal-audit-active.php,Transação READ ONLY; hashes; snapshots privados; guardas QA,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,estado-ativo-before/after; backup-proof e comparação de preservação,concluído e demonstrado,"Comparação temporal: 207 de 209 hashes iguais; cache/sessions diferem, causa não atribuída. Backup cobre todas as 288",Manter configurações/dumps privados; leituras não autorizam restauro sobre novas escritas,AUD-OPS-03: Leitor READ ONLY; hashes de negócio/histórico preservados; alterações técnicas cache/sessions explicitadas; restauro verifica 288 tabelas,P0,AUD-OPS-03: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-OPS-03,1,"[{""id"":""AUD-OPS-03"",""pedido"":""Leitura ativa e ensaios QA preservam dados/histórico"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Leitor READ ONLY; hashes de negócio/histórico preservados; alterações técnicas cache/sessions explicitadas; restauro verifica 288 tabelas"",""estado"":""concluído e demonstrado"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]","Não aplicável: requisito operacional, sem interface de utilizador",Guarda/teste de identidade e READ ONLY demonstrados,Escrita exclusiva QA; zero escrita ativa por estas ferramentas,Backup/restauro e hashes comparados,estado-ativo-before/after; backup-proof e comparação de preservação,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-HUMAN-01,"Identidade do operador, termos e contactos reais","Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",governação/outros,"Portal público, V2-02/V2-14",Configuração existente,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,Relatórios V2 mantêm a falta concreta,dependente de decisão concreta,Operador/termos/contactos não confirmados nesta auditoria,"Pergunta: qual a entidade operadora, contactos e versões de termos/política autorizadas para divulgação?",AUD-HUMAN-01: Publicar identidade/contactos/termos fornecidos pelo responsável; nunca inventar operador,P2,AUD-HUMAN-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-HUMAN-01,1,"[{""id"":""AUD-HUMAN-01"",""pedido"":""Identidade do operador, termos e contactos reais"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Publicar identidade/contactos/termos fornecidos pelo responsável; nunca inventar operador"",""estado"":""dependente de decisão concreta"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
@@ -3344,12 +3344,1020 @@ AUD-HUMAN-02,Links e serviços institucionais concretos,"Pedido direto 09/10/202
AUD-HUMAN-03,Modelo multicritério de sucesso/indicadores e pilotos,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",governação/outros,V2-09/V2-10/V2-14,Regras determinísticas/configurações existentes,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,Propostas conservadas nos mestres,dependente de decisão concreta,Modelo e baseline/pilotos não aprovados/medidos,"Pergunta: que pesos, limiares, baseline e responsáveis autorizados devem ser usados nos pilotos?","AUD-HUMAN-03: Pesos, período, limitações e revisão declarados; sem garantia automática",P2,AUD-HUMAN-03: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-HUMAN-03,1,"[{""id"":""AUD-HUMAN-03"",""pedido"":""Modelo multicritério de sucesso/indicadores e pilotos"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Pesos, período, limitações e revisão declarados; sem garantia automática"",""estado"":""dependente de decisão concreta"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-UX-01,Remover UUID interno sem utilidade no cartão da jornada,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",dashboard/perfis,/investidor,resources/js/pages/portfolio/workspace.tsx; referências internas preservadas,investment_accounts: 0; investment_company_declarations: 0; investment_submissions: 3,Código preparado; TypeScript/build passaram; ensaio visual pendente,parcial,UUID retirado da apresentação; restantes informações desnecessárias exigem percurso visual,Nenhuma alteração de dados,AUD-UX-01: Cartão identifica jornada pelo título e ações; gravação e relações continuam pelo mesmo ID,P2,AUD-UX-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-UX-01,1,"[{""id"":""AUD-UX-01"",""pedido"":""Remover UUID interno sem utilidade no cartão da jornada"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Cartão identifica jornada pelo título e ações; gravação e relações continuam pelo mesmo ID"",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""dashboard/perfis""}]",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-STYLE-01,Checks globais de formatação,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md",governação/outros,npm.cmd run check; php vendor/bin/pint --test,Formatadores existentes; corrigir por ficheiro sem alteração semântica,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,"check-lote2-final.log: formato global passa, lint 0 erros/11 avisos; pint-lote2-final.log passed; diff preservado",concluído e demonstrado,Critério de formatação encerrado; avisos lint preexistentes não foram omitidos e não equivalem a falha de persistência.,Sem decisão/instalação; mesmos formatadores existentes,AUD-STYLE-01: Checks globais passam; diff preserva comportamento e conteúdo documental,P2,AUD-STYLE-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-STYLE-01,1,"[{""id"":""AUD-STYLE-01"",""pedido"":""Checks globais de formatação"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md""],""aceitacao"":""Checks globais passam; diff preserva comportamento e conteúdo documental"",""estado"":""concluído e demonstrado"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Não aplicável a checks de formato,Não aplicável,Só ficheiros de código/documentação; dados ativos preservados,Checks relidos e resultados registados,Formatadores globais passam; nenhum erro lint,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-UI-01,Inspeção visual de todas as rotas/ações e botões,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",governação/outros,Inventário de 387 rotas; guiões por módulo,Browser control e provas históricas,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,"phpunit-lote3-final.xml, ações CRM/Bolsa/recursos/fundiário/correções Balcão por perfil; resultado GET/Inertia/eventos no servidor; consumer-actions-lote2.json atualizado:363 botões/272 seletores/mapas; browser getState vazio, chrome/edge indisponíveis mesmo após reset | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Interface integrada preparada, props Inertia e build verificados; nenhum provider de navegador disponível. Criação e nova sessão A/B na interface não demonstradas. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente.",parcial,"Resultado HTML/props/flash/API/persistência separado do resultado visual. QA HTTP recuperada em18096, provider de UI ausente; ligação de navegador solicitada. Não certificar todos os363 botões por suite/global/inventário. | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B.","Browser ligado e sessão QA; escrever somente na base QA | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-UI-01: Perfil autorizado; criar/editar/guardar/recuperar/pesquisar/filtros/anexos/excluir/transições; screenshots e rede por percurso | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-UI-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-UI-01,1,"[{""id"":""AUD-UI-01"",""pedido"":""Inspeção visual de todas as rotas/ações e botões"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Perfil autorizado; criar/editar/guardar/recuperar/pesquisar/filtros/anexos/excluir/transições; screenshots e rede por percurso | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]",Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente.,"Não demonstrado individualmente; localizar critério e executar em QA. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas.",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-UI-01,Inspeção visual de todas as rotas/ações e botões,"Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md | Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.",governação/outros,Inventário de 387 rotas; guiões por módulo,Browser control e provas históricas | [Perfis v1 QA10/10/2026] Reutilização/permissões organizacionais e workflow parcial nos AUD-PROFILE-01–32; nenhum sistema paralelo de identidades.,Requisito transversal; estado/configuração e snapshots descritos no relatório executivo,"phpunit-lote3-final.xml, ações CRM/Bolsa/recursos/fundiário/correções Balcão por perfil; resultado GET/Inertia/eventos no servidor; consumer-actions-lote2.json atualizado:363 botões/272 seletores/mapas; browser getState vazio, chrome/edge indisponíveis mesmo após reset | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Interface integrada preparada, props Inertia e build verificados; nenhum provider de navegador disponível. Criação e nova sessão A/B na interface não demonstradas. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | Complemento 2026-10-09T20:55:14.594455+00:00: investor-path-http-qa.json, login/logout e novo cookie jar autenticado; A/B próprios, pedidos/tarefas recuperados; troca de contexto403, outra conta403/draft404. Roteiro manual: roteiro-manual-qa-i0-i3.md. Sem UI observada. | C37 bloqueou cenário A na tentativa manual reportada: stack completa aponta users.two_factor_secret em TwoFactorLoginRequest::hasValidCode, não PreserveFormFeedback. mfa-key-diagnosis-qa.json demonstra segredo/recovery da conta13 legada incompatíveis com chaveQA; conta13 preservada, duas sessões QA invalidadas. Preparação/web agora partilham configuração estável/cache próprio, sem key:generate/rekey. mfa-auth-qa.xml e mfa-http-qa.json (2026-10-09T20:58:13.959848+00:00): novo investidor sintético com inscrição MFA normal Fortify, login/MFA/logout/nova sessão; falhas segredo/recovery controladas sem autenticação, redirect login com mensagem. CenárioA 413ba1f6-bdf6-402a-a561-c4e2d4098d1a criado, recuperado por nova sessão MFA, adaptado, ferramenta/resultado próprios, Balcão e tarefa interna concluída. Cookies/XSRF/OTP/corpos não exportados. Retoma visual continua pendente. | Histórico C37 REABERTO/P0, antes da captura21:22–21:24UTC: ciclo login da conta18 no navegador18097. auth-cookie-config-qa.json confirma atributos/guard QA; auth-session-trace-qa.jsonl preparado para primeira perda antes/depois MFA. Causa e continuidade visual não demonstradas; provas HTTP anteriores não fecham este caso. | C37 DIAGNÓSTICO CONFIRMADO/P0: manual21:22–21:24UTC desafia conta13, não18; POST/MFA21:23:04 falha na desencriptação e invalida intencionalmente; GET/login aceita nova sessão. Sem autenticação concluída/perda posterior/conflito de cookies. c37-manual-2122-2124-qa.json e c37-auth-redirect-qa.json: QA seleciona18, bloqueia restauradas antesMFA, apresenta erro da página; MFA18→/investimentos→reload→logout→nova sessão/dossier HTTP passou; visual18 pendente. | [QA dashboard 10/10/2026] dashboard-opportunities-http-qa.json: dashboard→destinos anunciados→create→201→GET→logout/nova sessão→GET→PUT→arquivo→filtro archived→restauro; QA13 mantém ID,4 eventos. dashboard-manager-mfa-http-qa.json: gestor17 MFA em duas sessões/reload/logout,0 registos alterados. 12 oportunidades anteriores, relações/documentos/dossiers preservados por SHA;6 publicadas mantidas. browser_visual_observed=false. | [Perfis v1 QA10/10/2026] Dashboard→novo draft15→recuperaçãoMFA→coedição21/22 HTTP; tipos/org/multirrole403; requestArchive persiste. Submissão422 por contrato completo ausente. VisualC37/C43/A-B pendente.",parcial,"Resultado HTML/props/flash/API/persistência separado do resultado visual. QA HTTP recuperada em18096, provider de UI ausente; ligação de navegador solicitada. Não certificar todos os363 botões por suite/global/inventário. | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes. | C37 corrigido por código/HTTP/persistência QA; repetir cenário A na interface com investidor sintético MFA, preservando o erro manual como histórico. | Histórico da reaberturaC37, antes da captura: localizar perda; corrigir causa e demonstrar /investimentos→reload→logout→novo login/MFA no navegador. | C37 após captura: causa conhecida e seleção/feedbackQA corrigidos; falta entrada visual bem-sucedida da conta18, reload/logout/nova sessão e retomaA/B. | [QA dashboard 10/10/2026] Navegador automático sem apps/browsers; C43 tem protocolo/persistência/assets demonstrados, visual pendente. C37 mantém pendência anterior sem novo login do investidor18. Roteiro curto de gestão com perfil17 em demonstracao-dashboard-oportunidades.md. | [Perfis v1 QA10/10/2026] Critérios específicos preservados; não confundir workflow parcial/props de menu com submissão/aprovação/publicação completas ou demonstração visual.","Browser ligado e sessão QA; escrever somente na base QA | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-UI-01: Perfil autorizado; criar/editar/guardar/recuperar/pesquisar/filtros/anexos/excluir/transições; screenshots e rede por percurso | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P0,AUD-UI-01: Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria,AUD-UI-01,1,"[{""id"":""AUD-UI-01"",""pedido"":""Inspeção visual de todas as rotas/ações e botões"",""fontes"":[""Pedido direto 09/10/2026, auditoria §1–4; fontes específicas descritas em relatorio-executivo.md"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md"",""Pedido direto 09/10/2026: corrigir HTTP500 POST /two-factor-challenge na QA18097 após conta13; preservar conta/chave/MFA, invalidar sessão exposta e retomar cenárioA.""],""aceitacao"":""Perfil autorizado; criar/editar/guardar/recuperar/pesquisar/filtros/anexos/excluir/transições; screenshots e rede por percurso | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""Relatórios históricos mantidos; estado ativo apurado por leitura nesta auditoria"",""modulo"":""governação/outros""}]","Manual: MFA13 alcançado e retorno/login observado21:22–21:24UTC; seleção/feedbackQA preparados. Sucesso visual da conta18/reload/logout/nova sessão pendente. | [QA dashboard 10/10/2026] C43/gestão e C37/investidor são ensaios independentes; ambos exigem navegador, não foram encerrados por HTTP.","Não demonstrado individualmente; localizar critério e executar em QA. | c37-auth-redirect-qa.json: redirects Inertia/HTML no servidor18097, MFA18 e negativas diferenciadas.",Não demonstrado individualmente; localizar critério e executar em QA.,Não demonstrado individualmente; localizar critério e executar em QA. | C37 nova sessão18 por HTTP recupera o dossier próprio apóslogout; outra conta403. Interface pendente.,Não demonstrado individualmente; localizar critério e executar em QA.,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-OP-05,Oito etapas de maturidade no cadastro de oportunidades,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",oportunidades,/management/opportunities/drafts; /management/opportunities/{id}/edit,OpportunityMaturity: spec-v2 (oito códigos) e legacy-v1 (seis posições); OpportunityManagement; seletor com catálogo recebido do servidor,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"PortalAuditNextLotTest; phpunit-lote2-final.log/xml; API/persistência/Inertia demonstradas, UI visual pendente; oito POST/GET; 7/8 201; replay único; 409; divergência código/posição 422; legado 6 mantém rótulo/coluna",parcial,"Rejeição 422 dos níveis 7/8 corrigida no draft. UI renderizada e adoção/revisão/publicação da nova versão continuam pendentes; filtros públicos continuam explicitamente na escala histórica, sem ler draft privado.",Sem migration adicional: etapa/posição/versão no management_draft existente. Workflow de publicação ainda pendente; nenhuma conversão automática dos seis valores antigos.,AUD-OP-05: Catálogo de oito etapas da especificação com versão explícita; guardar/recuperar etapas 7 e 8; preservar interpretação das seis etapas antigas; filtro e ficha coerentes,P1,"AUD-OP-05: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-OP-05,1,"[{""id"":""AUD-OP-05"",""pedido"":""Oito etapas de maturidade no cadastro de oportunidades"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Catálogo de oito etapas da especificação com versão explícita; guardar/recuperar etapas 7 e 8; preservar interpretação das seis etapas antigas; filtro e ficha coerentes"",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""oportunidades""}]",Oito etapas e opção histórica conservada; visual pendente,"POST draft 1–8 e PUT código/versão; inconsistência 422, conflito 409, outro perfil 403",management_draft guarda maturity_stage/level/catalogue_version; colunas históricas intactas; audit_events preservados,"GET edit recupera código, posição, rótulo e versão; catálogo server-side com oito entradas",Props do formulário verificadas; publicação/filtros públicos novos ainda pendentes,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-EDU-02,Rascunho incompleto privado de procura e capacidade,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",educação,/management/education/demands; /management/education/capacities,EducationController::store exige todos os campos e grava submitted; LabourDemand/TrainingCapacity existentes,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,pending-actions.json: quatro pedidos 422 na cópia restaurada; hashes de oportunidades/procura/capacidade/histórico inalterados; browser pendente,não implementado,Procura/capacidade incompletas recebem 422 sem gravação; não há percurso de rascunho incompleto. Rascunho de proposta de investimento e curso não satisfaz este pedido.,Executável em QA sem ClamD nem nova aceitação de fontes; dados/designações concretos apenas para utilização institucional ativa,"AUD-EDU-02: Guardar incompleto, editar com conflito, recuperar por dono; só submissão exige campos completos; revisão por ator distinto; rascunho fora dos agregados públicos",P1,"AUD-EDU-02: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-EDU-02,1,"[{""id"":""AUD-EDU-02"",""pedido"":""Rascunho incompleto privado de procura e capacidade"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Guardar incompleto, editar com conflito, recuperar por dono; só submissão exige campos completos; revisão por ator distinto; rascunho fora dos agregados públicos"",""estado"":""não implementado"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""educação""}]",Código inspecionado; browser pendente,QA reproduz 422; critério pedido continua a falhar,Nenhuma gravação nas tentativas incompletas/etapas 7–8; hashes conservados,Percurso solicitado ainda incompleto; não promover a concluído,Falha/lacuna documentada; inspeção visual pendente,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
AUD-EDU-03,Jornadas e painéis educativos por ator,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",educação,/educacao; /management/education,EducationController; schemas skills_edu; EducationInvestmentController,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,Inspeção de código e documentação; demonstração individual completa pendente,não implementado,Gestão interna e catálogo não demonstram nem implementam jornadas/painéis completos por ator; reutilizar atores/contas e schemas existentes.,Executável em QA sem ClamD nem nova aceitação de fontes; dados/designações concretos apenas para utilização institucional ativa,"AUD-EDU-03: Percurso próprio e ações autorizadas por estudante, entidade formadora, empregador e gestor conforme fontes; guardar/recuperar e isolamento; não presumir mandato institucional",P1,"AUD-EDU-03: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-EDU-03,1,"[{""id"":""AUD-EDU-03"",""pedido"":""Jornadas e painéis educativos por ator"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Percurso próprio e ações autorizadas por estudante, entidade formadora, empregador e gestor conforme fontes; guardar/recuperar e isolamento; não presumir mandato institucional"",""estado"":""não implementado"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""educação""}]",Código inspecionado; browser pendente,Não demonstrado individualmente,Não demonstrado individualmente,Percurso solicitado ainda incompleto; não promover a concluído,Falha/lacuna documentada; inspeção visual pendente,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-DOC-01,Reconciliar estados documentais antigos com evidências posteriores,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",governação/outros,docs/investmoz/v2/backlog-mestre.md; docs/investmoz/v2/gestao-oportunidades-dashboard.md,Matriz existente; relatórios históricos; snapshots ativos e testes atuais,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"Inspeção de código e documentação; demonstração individual completa pendente | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Aprovação expressa da execução QA recebida; fontes/IDs e versões históricas preservados, sem fecho automático de requisitos. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md.",parcial,"Contagens e novas correções reconciliadas nesta matriz; revisão semântica individual das cláusulas e demais estados documentais ainda pendente. Pedido anterior de PDFs preservado como histórico; pedido atual dispensa PDFs para continuar e aceita resumo/ativação na conversa. Revisão documental anterior não presumida pelos links Adobe. Sem dependência atual de gerar/anexar PDF. | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Executável em QA sem ClamD nem nova aceitação de fontes; dados/designações concretos apenas para utilização institucional ativa | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-DOC-01: Cada afirmação atual aponta para prova e data; versões antigas identificadas como históricas; divergência textual preservada; não apagar decisões anteriores | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P1,"AUD-DOC-01: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-DOC-01,1,"[{""id"":""AUD-DOC-01"",""pedido"":""Reconciliar estados documentais antigos com evidências posteriores"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Cada afirmação atual aponta para prova e data; versões antigas identificadas como históricas; divergência textual preservada; não apagar decisões anteriores | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""governação/outros""}]",Código inspecionado; browser pendente,Não demonstrado individualmente,Não demonstrado individualmente,Percurso solicitado ainda incompleto; não promover a concluído,Falha/lacuna documentada; inspeção visual pendente,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-COUNTRY-06,País pesquisável do proponente no wizard de negócios existentes,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",negócios,/investidor/negocios,BusinessFormSchema country/origin; CountrySelect no wizard; payload cifrado existente; filtros autorizados; agregado de negócios submetidos,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"PortalAuditNextLotTest; phpunit-lote2-final.log/xml; API/persistência/Inertia demonstradas, UI visual pendente | continuation-consumer-qa.xml: provas individuais país/origem/filtro/estatística, incluindo quatro tipos de apoio e três serviços Balcão após correção; continuation-profile-qa.xml: perfil/empresa/submissão/CRM; continuation-business-journey-qa.xml: formulário de interesse em negócio público PT/ZA/recibo/replay/GET/filtro/estatística e jornada PT=1/MZ=0 sem inferir país. Ver cobertura-percursos-i0-i3.md, sem promover API/props a UI.",parcial,Percurso API/gravação/recuperação/filtros/estatísticas demonstrado individualmente. Visual atual pendente; não encerrar cobertura transversal por este formulário.,"Sem migration ou ClamD; países existentes. Origem opcional explicitamente declarada, sem inferência a partir de residência/constituição.",AUD-COUNTRY-06: Catálogo ISO pesquisável; código válido guardado e recuperado no payload canónico; valor legado visível/conservado; ZZ 422 sem versão nova; outra conta negada,P1,"AUD-COUNTRY-06: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-COUNTRY-06,1,"[{""id"":""AUD-COUNTRY-06"",""pedido"":""País pesquisável do proponente no wizard de negócios existentes"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Catálogo ISO pesquisável; código válido guardado e recuperado no payload canónico; valor legado visível/conservado; ZZ 422 sem versão nova; outra conta negada"",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""negócios""}]",CountrySelect para país e origem; props 249; visual pendente,POST/PUT/GET listings; submissão privada; country/origin filters; outra conta 403/lista vazia,País PT/origem ZA separados no payload cifrado; ZZ 422 conserva versão; sem tabela paralela,GET recupera ambos; countryName/declaredOrigin no consumidor; negócios excluem drafts dos agregados; fundiário integra interesses uma vez,"Props, filtros e agregados verificados; UI ainda sem demonstração visual",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-COUNTRY-07,País pesquisável no formulário de assistência fundiária,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",oportunidades,/investidor/terra-duat,CountrySelect fundiário; payload cifrado; origem mantida no CRM/receipt; nomes e caminho territorial recuperados na ficha,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"PortalAuditNextLotTest; phpunit-lote2-final.log/xml; API/persistência/Inertia demonstradas, UI visual pendente | continuation-consumer-qa.xml: provas individuais país/origem/filtro/estatística, incluindo quatro tipos de apoio e três serviços Balcão após correção; continuation-profile-qa.xml: perfil/empresa/submissão/CRM; continuation-business-journey-qa.xml: formulário de interesse em negócio público PT/ZA/recibo/replay/GET/filtro/estatística e jornada PT=1/MZ=0 sem inferir país. Ver cobertura-percursos-i0-i3.md, sem promover API/props a UI.",parcial,Percurso API/gravação/recuperação/filtros/estatísticas demonstrado individualmente. Visual atual pendente; não encerrar cobertura transversal por este formulário.,"Sem migration ou ClamD; países existentes. Origem opcional explicitamente declarada, sem inferência a partir de residência/constituição.",AUD-COUNTRY-07: Catálogo ISO pesquisável opcional; guardar/recuperar país sem inventar nacionalidade/origem; legado exato; erro no campo e privacidade,P1,"AUD-COUNTRY-07: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-COUNTRY-07,1,"[{""id"":""AUD-COUNTRY-07"",""pedido"":""País pesquisável no formulário de assistência fundiária"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Catálogo ISO pesquisável opcional; guardar/recuperar país sem inventar nacionalidade/origem; legado exato; erro no campo e privacidade"",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""oportunidades""}]",CountrySelect para país e origem; props 249; visual pendente,POST/PUT/GET caso; solicitar-apoio; gestor filtra país/origem; outra conta 404/403,País PT/origem ZA separados no payload cifrado; ZZ 422 conserva versão; sem tabela paralela,GET recupera ambos; countryName/declaredOrigin no consumidor; negócios excluem drafts dos agregados; fundiário integra interesses uma vez,"Props, filtros e agregados verificados; UI ainda sem demonstração visual",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-COUNTRY-05,Catálogo HTTP ISO comum independente da publicação de jurisdições,"Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria",simuladores,/api/v1/catalogs/countries,CountryCatalogue; ReferenceCatalogController,"Catálogo local 249, sem migration; consumidor novo ainda não demonstrado no web ativo","PortalAuditContinuationTest: 5 testes / 203 asserções; phpunit-followup-recovery-final.log; API/Inertia/persistência demonstradas, browser indisponível",concluído e demonstrado,Critério restrito à API em QA; os requisitos de formulários/cartografia global continuam parciais,Não depende de ClamD; nenhum dado inventado ou importação ativa,AUD-COUNTRY-05: API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions,P1,AUD-COUNTRY-05: Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03,AUD-COUNTRY-05,1,"[{""id"":""AUD-COUNTRY-05"",""pedido"":""Catálogo HTTP ISO comum independente da publicação de jurisdições"",""fontes"":[""Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria""],""aceitacao"":""API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions"",""estado"":""concluído e demonstrado"",""variantes"":""Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03"",""modulo"":""simuladores""}]",Não aplicável ao critério de catálogo HTTP; consumidores de UI mantidos parciais,"PortalAuditContinuationTest: 5 testes / 203 asserções; phpunit-followup-recovery-final.log; API/Inertia/persistência demonstradas, browser indisponível",Catálogo somente leitura; não altera dados,API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions,Resposta JSON comparada; não certifica UI ou mapas,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
-AUD-GEO-04,Recuperação integral do catálogo administrativo público pela API hierárquica,"Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria",cartografia/relações,/api/v1/investment/territory-options,InvestmentTerritoryController; geo_locations existentes,Cadastro ativo 1990; públicos administrativos 1920; geo_geometries=0,territory-catalogue-coverage.json: QA 55441; 597 pedidos; 1920/1920 IDs; escrita ativa=0,concluído e demonstrado,Critério restrito à API em QA; os requisitos de formulários/cartografia global continuam parciais,Não depende de ClamD; nenhum dado inventado ou importação ativa,"AUD-GEO-04: Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores",P1,AUD-GEO-04: Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03,AUD-GEO-04,1,"[{""id"":""AUD-GEO-04"",""pedido"":""Recuperação integral do catálogo administrativo público pela API hierárquica"",""fontes"":[""Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria""],""aceitacao"":""Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores"",""estado"":""concluído e demonstrado"",""variantes"":""Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03"",""modulo"":""cartografia/relações""}]",Não aplicável ao critério de catálogo HTTP; consumidores de UI mantidos parciais,territory-catalogue-coverage.json: QA 55441; 597 pedidos; 1920/1920 IDs; escrita ativa=0,Catálogo somente leitura; não altera dados,"Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores",Resposta JSON comparada; não certifica UI ou mapas,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-DOC-01,Reconciliar estados documentais antigos com evidências posteriores,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz | Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas | Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md",governação/outros,docs/investmoz/v2/backlog-mestre.md; docs/investmoz/v2/gestao-oportunidades-dashboard.md,Matriz existente; relatórios históricos; snapshots ativos e testes atuais,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"Inspeção de código e documentação; demonstração individual completa pendente | Complemento de leitura: investor-consolidation-runtime.json (2026-10-09T19:03:32+00:00, READ ONLY), assistant-source-full.json; Aprovação expressa da execução QA recebida; fontes/IDs e versões históricas preservados, sem fecho automático de requisitos. Execução QA aprovada I1–I3. Revisão QA atual: ba3781ad7af15b02c3021e69081f4129a2a19339fd740094d39e913f3657977c, com provas dirigidas/HTTP identificadas abaixo. Regressão histórica: 384 ensaios globais, hash e29eb8c4b11fce6aa78c798e24330bbf96efbea7ac2eb39c3f03b978caeef076; path-focused.xml (32/541) e path-followup.xml (26/551) são anteriores. Cenários A/B API/persistência, UI pendente; execucao-percurso-i1-i3.md. | [QA dashboard 10/10/2026] Mesma matriz3354requisitos/5830ocorrências preserva fontes/trechos/IDs/versões por SHA; apenasAUD-OP-04 muda não implementado→parcial pelo incremento específicoAPI. Lista integral de3349abertos derivada desta matriz,sem estados independentes nem segunda matriz.",parcial,"Contagens e novas correções reconciliadas nesta matriz; revisão semântica individual das cláusulas e demais estados documentais ainda pendente. Pedido anterior de PDFs preservado como histórico; pedido atual dispensa PDFs para continuar e aceita resumo/ativação na conversa. Revisão documental anterior não presumida pelos links Adobe. Sem dependência atual de gerar/anexar PDF. | Execução estrutural QA aprovada e preparada; instalação ativa, cenários A/B na interface e cobertura de todos os consumidores permanecem pendentes.","Executável em QA sem ClamD nem nova aceitação de fontes; dados/designações concretos apenas para utilização institucional ativa | I1–I3 autorizados exclusivamente em QA: concluir demonstração A/B na interface, cobertura de contexto/prefill e provas da versão. Ativação ativa não autorizada. I0 continua independente.","AUD-DOC-01: Cada afirmação atual aponta para prova e data; versões antigas identificadas como históricas; divergência textual preservada; não apagar decisões anteriores | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente.",P1,"AUD-DOC-01: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-DOC-01,1,"[{""id"":""AUD-DOC-01"",""pedido"":""Reconciliar estados documentais antigos com evidências posteriores"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz"",""Pedido direto 09/10/2026, lote 3: ações por perfil, países/seletores, geometria por consumidor, navegador, ativação separada e PDFs diretos; sem jornadas educativas novas"",""Proposta consolidação 09/10/2026; DOCX aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364; texto P22–P40, estados P76–P88, aprovação P326/P497; proposta-consolidacao-percurso.md""],""aceitacao"":""Cada afirmação atual aponta para prova e data; versões antigas identificadas como históricas; divergência textual preservada; não apagar decisões anteriores | Para consolidação: critérios individuais S01–S19 e cenários A/B na proposta, com UI→API→gravação→nova sessão→resultado e ação independente."",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""governação/outros""}]",Código inspecionado; browser pendente,Não demonstrado individualmente,Não demonstrado individualmente,Percurso solicitado ainda incompleto; não promover a concluído,Falha/lacuna documentada; inspeção visual pendente,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-COUNTRY-06,País pesquisável do proponente no wizard de negócios existentes,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",negócios,/investidor/negocios,BusinessFormSchema country/origin; CountrySelect no wizard; payload cifrado existente; filtros autorizados; agregado de negócios submetidos,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"PortalAuditNextLotTest; phpunit-lote2-final.log/xml; API/persistência/Inertia demonstradas, UI visual pendente | continuation-consumer-qa.xml: provas individuais país/origem/filtro/estatística, incluindo quatro tipos de apoio e três serviços Balcão após correção; continuation-profile-qa.xml: perfil/empresa/submissão/CRM; continuation-business-journey-qa.xml: formulário de interesse em negócio público PT/ZA/recibo/replay/GET/filtro/estatística e jornada PT=1/MZ=0 sem inferir país. Ver cobertura-percursos-i0-i3.md, sem promover API/props a UI. | [QA independente 10/10/2026] countries-independent-qa.xml: métodos específicos InvestmentWorkspaceTest(perfil/empresa/manifestação/CRM), PortalAuditContinuationTest(público/quatro apoios/catálogo/Balcão territorial), PortalAuditNextLotTest(negócios/fundiário), PortalOriginCompatibilityTest(origem legada) e InvestorGuidanceTest(Balcão). countries-forms-independent-qa.xml: métodos próprios do interesse público em negócio, jornada da carteira, três serviços Balcão e simulador. Cobertura por formulário em cobertura-percursos-i0-i3.md; a expressão original em nomes de testes também seleciona testes documentais, não contar22 requisitos/percursos de países.",parcial,"Histórico até09/10 (preservado): Percurso API/gravação/recuperação/filtros/estatísticas demonstrado individualmente. Visual atual pendente; não encerrar cobertura transversal por este formulário. | [QA independente 10/10/2026] API/gravação/recuperação/filtros/agregados têm provas por formulário identificado; seleção, feedback, variações condicionais e apresentação de filtros/tabela/nova sessão no navegador continuam pendentes. Não inferir origem da residência/constituição/fiscal/fundos; faltas históricas permanecem Não informado.","Sem migration ou ClamD; países existentes. Origem opcional explicitamente declarada, sem inferência a partir de residência/constituição.",AUD-COUNTRY-06: Catálogo ISO pesquisável; código válido guardado e recuperado no payload canónico; valor legado visível/conservado; ZZ 422 sem versão nova; outra conta negada,P1,"AUD-COUNTRY-06: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-COUNTRY-06,1,"[{""id"":""AUD-COUNTRY-06"",""pedido"":""País pesquisável do proponente no wizard de negócios existentes"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Catálogo ISO pesquisável; código válido guardado e recuperado no payload canónico; valor legado visível/conservado; ZZ 422 sem versão nova; outra conta negada"",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""negócios""}]",CountrySelect para país e origem; props 249; visual pendente | [QA independente 10/10/2026] Componentes já existentes; nenhuma nova confirmação visual neste lote.,"POST/PUT/GET listings; submissão privada; country/origin filters; outra conta 403/lista vazia | [QA independente 10/10/2026] Ensaios de rotas reais no kernel QA: códigos ISO inválidos422 sem escrita, replay idempotente, versões409 e acesso indevido403/404, conforme formulário.","País PT/origem ZA separados no payload cifrado; ZZ 422 conserva versão; sem tabela paralela | [QA independente 10/10/2026] Valores separados e revisões/snapshot por formulário, fora da base ativa; rascunhos não contaminam agregados de submissões.",GET recupera ambos; countryName/declaredOrigin no consumidor; negócios excluem drafts dos agregados; fundiário integra interesses uma vez | [QA independente 10/10/2026] GET/listas/filtros próprios demonstrados por método; diferente conta recusada. Não equivalem a nova sessão de navegador.,"Props, filtros e agregados verificados; UI ainda sem demonstração visual | [QA independente 10/10/2026] Recibos/props/JSON/filtros/estatísticas de interests, desk e businesses separados; renderização pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-COUNTRY-07,País pesquisável no formulário de assistência fundiária,"Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz",oportunidades,/investidor/terra-duat,CountrySelect fundiário; payload cifrado; origem mantida no CRM/receipt; nomes e caminho territorial recuperados na ficha,Consultar snapshot READ ONLY de 16:17:55 UTC; nenhum dado ativo alterado,"PortalAuditNextLotTest; phpunit-lote2-final.log/xml; API/persistência/Inertia demonstradas, UI visual pendente | continuation-consumer-qa.xml: provas individuais país/origem/filtro/estatística, incluindo quatro tipos de apoio e três serviços Balcão após correção; continuation-profile-qa.xml: perfil/empresa/submissão/CRM; continuation-business-journey-qa.xml: formulário de interesse em negócio público PT/ZA/recibo/replay/GET/filtro/estatística e jornada PT=1/MZ=0 sem inferir país. Ver cobertura-percursos-i0-i3.md, sem promover API/props a UI. | [QA independente 10/10/2026] countries-independent-qa.xml: métodos específicos InvestmentWorkspaceTest(perfil/empresa/manifestação/CRM), PortalAuditContinuationTest(público/quatro apoios/catálogo/Balcão territorial), PortalAuditNextLotTest(negócios/fundiário), PortalOriginCompatibilityTest(origem legada) e InvestorGuidanceTest(Balcão). countries-forms-independent-qa.xml: métodos próprios do interesse público em negócio, jornada da carteira, três serviços Balcão e simulador. Cobertura por formulário em cobertura-percursos-i0-i3.md; a expressão original em nomes de testes também seleciona testes documentais, não contar22 requisitos/percursos de países.",parcial,"Histórico até09/10 (preservado): Percurso API/gravação/recuperação/filtros/estatísticas demonstrado individualmente. Visual atual pendente; não encerrar cobertura transversal por este formulário. | [QA independente 10/10/2026] API/gravação/recuperação/filtros/agregados têm provas por formulário identificado; seleção, feedback, variações condicionais e apresentação de filtros/tabela/nova sessão no navegador continuam pendentes. Não inferir origem da residência/constituição/fiscal/fundos; faltas históricas permanecem Não informado.","Sem migration ou ClamD; países existentes. Origem opcional explicitamente declarada, sem inferência a partir de residência/constituição.",AUD-COUNTRY-07: Catálogo ISO pesquisável opcional; guardar/recuperar país sem inventar nacionalidade/origem; legado exato; erro no campo e privacidade,P1,"AUD-COUNTRY-07: O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido",AUD-COUNTRY-07,1,"[{""id"":""AUD-COUNTRY-07"",""pedido"":""País pesquisável no formulário de assistência fundiária"",""fontes"":[""Pedido direto 09/10/2026, principais lacunas e continuação; docs/investmoz/v2/gestao-oportunidades-dashboard.md §10; referências originais conservadas na matriz""],""aceitacao"":""Catálogo ISO pesquisável opcional; guardar/recuperar país sem inventar nacionalidade/origem; legado exato; erro no campo e privacidade"",""estado"":""parcial"",""variantes"":""O relatório indicado em outputs/auditoria-portal-2026-10-09.md não foi localizado neste workspace; conteúdo da mensagem preservado como fonte direta, sem atribuir hash ao ficheiro não lido"",""modulo"":""oportunidades""}]",CountrySelect para país e origem; props 249; visual pendente | [QA independente 10/10/2026] Componentes já existentes; nenhuma nova confirmação visual neste lote.,"POST/PUT/GET caso; solicitar-apoio; gestor filtra país/origem; outra conta 404/403 | [QA independente 10/10/2026] Ensaios de rotas reais no kernel QA: códigos ISO inválidos422 sem escrita, replay idempotente, versões409 e acesso indevido403/404, conforme formulário.","País PT/origem ZA separados no payload cifrado; ZZ 422 conserva versão; sem tabela paralela | [QA independente 10/10/2026] Valores separados e revisões/snapshot por formulário, fora da base ativa; rascunhos não contaminam agregados de submissões.",GET recupera ambos; countryName/declaredOrigin no consumidor; negócios excluem drafts dos agregados; fundiário integra interesses uma vez | [QA independente 10/10/2026] GET/listas/filtros próprios demonstrados por método; diferente conta recusada. Não equivalem a nova sessão de navegador.,"Props, filtros e agregados verificados; UI ainda sem demonstração visual | [QA independente 10/10/2026] Recibos/props/JSON/filtros/estatísticas de interests, desk e businesses separados; renderização pendente.",Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-COUNTRY-05,Catálogo HTTP ISO comum independente da publicação de jurisdições,"Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria",simuladores,/api/v1/catalogs/countries,CountryCatalogue; ReferenceCatalogController,"Catálogo local 249, sem migration; consumidor novo ainda não demonstrado no web ativo","PortalAuditContinuationTest: 5 testes / 203 asserções; phpunit-followup-recovery-final.log; API/Inertia/persistência demonstradas, browser indisponível | [QA independente 10/10/2026] Catálogo ISO independente: método próprio PortalAuditContinuationTest em countries-independent-qa.xml renovado;249 países/pesquisa/paginação. Fecho restrito à API mantém-se, não fecha todos os formulários.",concluído e demonstrado,Critério restrito à API em QA; os requisitos de formulários/cartografia global continuam parciais,Não depende de ClamD; nenhum dado inventado ou importação ativa,AUD-COUNTRY-05: API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions,P1,AUD-COUNTRY-05: Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03,AUD-COUNTRY-05,1,"[{""id"":""AUD-COUNTRY-05"",""pedido"":""Catálogo HTTP ISO comum independente da publicação de jurisdições"",""fontes"":[""Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria""],""aceitacao"":""API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions"",""estado"":""concluído e demonstrado"",""variantes"":""Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03"",""modulo"":""simuladores""}]",Não aplicável ao critério de catálogo HTTP; consumidores de UI mantidos parciais,"PortalAuditContinuationTest: 5 testes / 203 asserções; phpunit-followup-recovery-final.log; API/Inertia/persistência demonstradas, browser indisponível",Catálogo somente leitura; não altera dados,API retorna 249 códigos únicos paginados; pesquisa PT/EN/código e sem acentos; parâmetros incompatíveis 422; zero seed em geo_locations/reference_catalog_versions,Resposta JSON comparada; não certifica UI ou mapas,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-GEO-04,Recuperação integral do catálogo administrativo público pela API hierárquica,"Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria",cartografia/relações,/api/v1/investment/territory-options,InvestmentTerritoryController; geo_locations existentes,Cadastro ativo 1990; públicos administrativos 1920; geo_geometries=0,territory-catalogue-coverage.json: QA 55441; 597 pedidos; 1920/1920 IDs; escrita ativa=0 | [QA independente 10/10/2026] Atualização READ ONLY territory-catalogue-coverage.json: alvo desk_restore_20261009_174726_test:55441;597 consultas/1920 IDs/0omissões. Critério API restrito já demonstrado; não fecha campos/mapas.,concluído e demonstrado,Critério restrito à API em QA; os requisitos de formulários/cartografia global continuam parciais,Não depende de ClamD; nenhum dado inventado ou importação ativa,"AUD-GEO-04: Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores",P1,AUD-GEO-04: Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03,AUD-GEO-04,1,"[{""id"":""AUD-GEO-04"",""pedido"":""Recuperação integral do catálogo administrativo público pela API hierárquica"",""fontes"":[""Pedido direto 09/10/2026, continuação §2–4; caso adicional encontrado na auditoria""],""aceitacao"":""Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores"",""estado"":""concluído e demonstrado"",""variantes"":""Caso novo; não substitui AUD-COUNTRY-01–04 / AUD-GEO-01–03"",""modulo"":""cartografia/relações""}]",Não aplicável ao critério de catálogo HTTP; consumidores de UI mantidos parciais,territory-catalogue-coverage.json: QA 55441; 597 pedidos; 1920/1920 IDs; escrita ativa=0,Catálogo somente leitura; não altera dados,"Na cópia restaurada, comparar todos os IDs públicos por tipo/pai/página sem omissões nem duplicados: 11/148/437/1324; não inclui mapas/geometrias nem persistência de todos os consumidores",Resposta JSON comparada; não certifica UI ou mapas,Texto exatamente equivalente no mesmo módulo; sem fusão semântica aproximada
+AUD-PROFILE-01,"Seis perfis sobre identidades existentes, com RBAC e ABAC","Gestao de perfis investeMOZ v1.docx | parágrafo 1 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 2 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 3 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 5 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 7 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 8 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 9 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 10 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 11 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 12 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 13 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 14 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 15 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 16 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 17 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 18 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 20 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 21 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 22 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 24 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 25 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 26 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 27 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 28 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 29 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 30 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 31 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 33 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 34 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 35 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 36 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 37 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 38 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 39 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 40 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 44 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 47 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 52 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 60 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 61 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 62 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 63 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 64 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 65 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 67 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 68 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 69 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 70 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 71 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 72 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 74 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 78 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 79 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 80 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 81 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 82 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 83 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 84 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 86 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 87 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 88 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 89 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 90 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 91 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 92 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 93 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 94 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 95 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 96 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 97 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 98 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 101 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 102 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 103 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 104 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 105 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 106 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 108 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 110 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 111 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 112 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 115 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 116 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 117 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 118 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 119 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 120 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 122 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 124 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 125 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 126 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 127 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 129 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 130 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 131 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 132 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 133 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 136 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 137 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 138 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 139 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 140 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 141 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 143 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 144 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 146 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 147 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 150 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 151 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 152 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 153 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 154 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 155 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 157 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 158 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 159 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 160 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 161 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 162 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 163 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 164 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 165 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 166 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 167 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 168 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 170 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 173 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 175 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 177 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 178 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 179 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 180 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 182 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 184 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 189 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 190 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 191 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 194 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 195 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 196 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 197 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 198 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 199 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 200 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 201 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 202 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 203 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 205 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 208 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 209 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 210 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 212 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 213 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 215 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 216 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 217 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 218 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 219 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 220 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 222 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 223 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 224 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 225 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 226 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 228 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 230 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 231 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 233 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 234 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 235 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 238 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 240 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 243 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 244 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 245 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 246 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 248 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 250 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 253 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 255 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 256 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 258 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 259 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 260 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 262 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 263 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 270 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 272 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 273 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 274 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 275 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 277 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 278 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 281 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 285 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 286 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 287 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 288 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 289 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 297 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 299 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 301 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 303 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 304 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 305 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 307 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 314 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 315 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 316 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 317 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 318 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 320 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 321 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 323 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 325 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 327 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 330 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 331 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 338 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 351 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 354 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 355 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 356 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 358 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 359 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 360 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 361 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 363 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 364 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 365 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 366 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 367 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 370 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 374 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 376 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 379 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 380 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 382 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 388 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 391 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 392 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 393 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 394 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 395 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 396 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 502 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 503 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 504 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 505 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 506 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 507 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 518 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 519 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 520 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 521 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 522 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 523 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 529 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 530 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 1 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 3 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 4 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 5 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 6 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 7 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 8 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 9 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 11 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 15 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 23 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 31 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 32 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 33 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 34 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 35 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 36 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 38 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 39 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 40 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 47 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 48 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 49 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 50 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 51 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 52 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 53 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 55 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 56 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 57 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 58 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 59 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 60 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 61 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 62 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 63 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 64 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 65 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 66 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 67 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 70 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 71 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 72 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 73 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 74 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 75 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 77 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 79 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 80 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 81 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 84 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 85 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 86 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 87 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 88 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 89 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 91 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 93 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 94 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 95 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 96 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 98 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 99 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 100 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 101 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 102 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 105 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 106 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 107 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 108 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 109 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 110 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 112 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 113 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 115 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 116 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 119 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 120 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 121 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 122 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 123 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 124 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 126 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 127 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 128 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 129 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 130 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 131 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 132 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 133 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 134 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 135 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 136 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 137 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 139 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 142 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 144 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 146 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 147 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 148 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 149 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 151 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 153 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 158 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 159 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 160 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 163 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 164 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 165 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 166 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 167 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 168 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 169 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 170 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 171 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 172 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 174 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 177 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 178 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 179 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 182 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 184 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 185 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 187 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 188 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 189 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 192 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 193 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 194 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 195 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 197 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 199 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 200 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 202 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 203 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 204 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 207 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 209 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 212 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 213 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 214 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 215 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 217 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 219 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 222 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 224 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 225 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 227 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 228 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 229 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 232 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 237 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 239 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 241 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 242 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 243 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 244 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 246 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 247 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 250 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 254 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 255 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 256 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 257 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 258 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 266 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 268 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 270 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 272 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 273 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 274 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 276 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 283 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 284 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 285 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 286 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 287 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 289 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 290 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 292 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 294 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 296 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 299 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 300 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 306 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 307 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 314 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 319 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 322 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 323 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 324 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 326 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 327 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 328 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 329 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 331 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 332 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 333 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 334 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 335 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 338 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 342 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 344 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 347 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 348 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 350 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 356 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 359 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 360 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 361 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 362 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 363 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 364 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 470 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 471 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"PortalProfileAccess; users/Fortify, organizations/memberships, quatro atribuições operacionais e dupla controlada; público derivado de conta verificada.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Doze atores normais MFA e consultas por perfil no servidor QA; schema ligado às entidades canónicas. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,Âmbito provincial ainda não modelado; migração reconciliada dos gestores legados e aceitação visual por perfil.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0001;PROFILEV1-P0002;PROFILEV1-P0003;PROFILEV1-P0005;PROFILEV1-P0007;PROFILEV1-P0008;PROFILEV1-P0009;PROFILEV1-P0010;PROFILEV1-P0011;PROFILEV1-P0012;PROFILEV1-P0013;PROFILEV1-P0014;PROFILEV1-P0015;PROFILEV1-P0016;PROFILEV1-P0017;PROFILEV1-P0018;PROFILEV1-P0020;PROFILEV1-P0021;PROFILEV1-P0022;PROFILEV1-P0024;PROFILEV1-P0025;PROFILEV1-P0026;PROFILEV1-P0027;PROFILEV1-P0028;PROFILEV1-P0029;PROFILEV1-P0030;PROFILEV1-P0031;PROFILEV1-P0033;PROFILEV1-P0034;PROFILEV1-P0035;PROFILEV1-P0036;PROFILEV1-P0037;PROFILEV1-P0038;PROFILEV1-P0039;PROFILEV1-P0040;PROFILEV1-P0044;PROFILEV1-P0047;PROFILEV1-P0052;PROFILEV1-P0060;PROFILEV1-P0061;PROFILEV1-P0062;PROFILEV1-P0063;PROFILEV1-P0064;PROFILEV1-P0065;PROFILEV1-P0067;PROFILEV1-P0068;PROFILEV1-P0069;PROFILEV1-P0070;PROFILEV1-P0071;PROFILEV1-P0072;PROFILEV1-P0074;PROFILEV1-P0078;PROFILEV1-P0079;PROFILEV1-P0080;PROFILEV1-P0081;PROFILEV1-P0082;PROFILEV1-P0083;PROFILEV1-P0084;PROFILEV1-P0086;PROFILEV1-P0087;PROFILEV1-P0088;PROFILEV1-P0089;PROFILEV1-P0090;PROFILEV1-P0091;PROFILEV1-P0092;PROFILEV1-P0093;PROFILEV1-P0094;PROFILEV1-P0095;PROFILEV1-P0096;PROFILEV1-P0097;PROFILEV1-P0098;PROFILEV1-P0101;PROFILEV1-P0102;PROFILEV1-P0103;PROFILEV1-P0104;PROFILEV1-P0105;PROFILEV1-P0106;PROFILEV1-P0108;PROFILEV1-P0110;PROFILEV1-P0111;PROFILEV1-P0112;PROFILEV1-P0115;PROFILEV1-P0116;PROFILEV1-P0117;PROFILEV1-P0118;PROFILEV1-P0119;PROFILEV1-P0120;PROFILEV1-P0122;PROFILEV1-P0124;PROFILEV1-P0125;PROFILEV1-P0126;PROFILEV1-P0127;PROFILEV1-P0129;PROFILEV1-P0130;PROFILEV1-P0131;PROFILEV1-P0132;PROFILEV1-P0133;PROFILEV1-P0136;PROFILEV1-P0137;PROFILEV1-P0138;PROFILEV1-P0139;PROFILEV1-P0140;PROFILEV1-P0141;PROFILEV1-P0143;PROFILEV1-P0144;PROFILEV1-P0146;PROFILEV1-P0147;PROFILEV1-P0150;PROFILEV1-P0151;PROFILEV1-P0152;PROFILEV1-P0153;PROFILEV1-P0154;PROFILEV1-P0155;PROFILEV1-P0157;PROFILEV1-P0158;PROFILEV1-P0159;PROFILEV1-P0160;PROFILEV1-P0161;PROFILEV1-P0162;PROFILEV1-P0163;PROFILEV1-P0164;PROFILEV1-P0165;PROFILEV1-P0166;PROFILEV1-P0167;PROFILEV1-P0168;PROFILEV1-P0170;PROFILEV1-P0173;PROFILEV1-P0175;PROFILEV1-P0177;PROFILEV1-P0178;PROFILEV1-P0179;PROFILEV1-P0180;PROFILEV1-P0182;PROFILEV1-P0184;PROFILEV1-P0189;PROFILEV1-P0190;PROFILEV1-P0191;PROFILEV1-P0194;PROFILEV1-P0195;PROFILEV1-P0196;PROFILEV1-P0197;PROFILEV1-P0198;PROFILEV1-P0199;PROFILEV1-P0200;PROFILEV1-P0201;PROFILEV1-P0202;PROFILEV1-P0203;PROFILEV1-P0205;PROFILEV1-P0208;PROFILEV1-P0209;PROFILEV1-P0210;PROFILEV1-P0212;PROFILEV1-P0213;PROFILEV1-P0215;PROFILEV1-P0216;PROFILEV1-P0217;PROFILEV1-P0218;PROFILEV1-P0219;PROFILEV1-P0220;PROFILEV1-P0222;PROFILEV1-P0223;PROFILEV1-P0224;PROFILEV1-P0225;PROFILEV1-P0226;PROFILEV1-P0228;PROFILEV1-P0230;PROFILEV1-P0231;PROFILEV1-P0233;PROFILEV1-P0234;PROFILEV1-P0235;PROFILEV1-P0238;PROFILEV1-P0240;PROFILEV1-P0243;PROFILEV1-P0244;PROFILEV1-P0245;PROFILEV1-P0246;PROFILEV1-P0248;PROFILEV1-P0250;PROFILEV1-P0253;PROFILEV1-P0255;PROFILEV1-P0256;PROFILEV1-P0258;PROFILEV1-P0259;PROFILEV1-P0260;PROFILEV1-P0262;PROFILEV1-P0263;PROFILEV1-P0270;PROFILEV1-P0272;PROFILEV1-P0273;PROFILEV1-P0274;PROFILEV1-P0275;PROFILEV1-P0277;PROFILEV1-P0278;PROFILEV1-P0281;PROFILEV1-P0285;PROFILEV1-P0286;PROFILEV1-P0287;PROFILEV1-P0288;PROFILEV1-P0289;PROFILEV1-P0297;PROFILEV1-P0299;PROFILEV1-P0301;PROFILEV1-P0303;PROFILEV1-P0304;PROFILEV1-P0305;PROFILEV1-P0307;PROFILEV1-P0314;PROFILEV1-P0315;PROFILEV1-P0316;PROFILEV1-P0317;PROFILEV1-P0318;PROFILEV1-P0320;PROFILEV1-P0321;PROFILEV1-P0323;PROFILEV1-P0325;PROFILEV1-P0327;PROFILEV1-P0330;PROFILEV1-P0331;PROFILEV1-P0338;PROFILEV1-P0351;PROFILEV1-P0354;PROFILEV1-P0355;PROFILEV1-P0356;PROFILEV1-P0358;PROFILEV1-P0359;PROFILEV1-P0360;PROFILEV1-P0361;PROFILEV1-P0363;PROFILEV1-P0364;PROFILEV1-P0365;PROFILEV1-P0366;PROFILEV1-P0367;PROFILEV1-P0370;PROFILEV1-P0374;PROFILEV1-P0376;PROFILEV1-P0379;PROFILEV1-P0380;PROFILEV1-P0382;PROFILEV1-P0388;PROFILEV1-P0391;PROFILEV1-P0392;PROFILEV1-P0393;PROFILEV1-P0394;PROFILEV1-P0395;PROFILEV1-P0396;PROFILEV1-P0502;PROFILEV1-P0503;PROFILEV1-P0504;PROFILEV1-P0505;PROFILEV1-P0506;PROFILEV1-P0507;PROFILEV1-P0518;PROFILEV1-P0519;PROFILEV1-P0520;PROFILEV1-P0521;PROFILEV1-P0522;PROFILEV1-P0523;PROFILEV1-P0529;PROFILEV1-P0530;PROFILEOLD-P0001;PROFILEOLD-P0003;PROFILEOLD-P0004;PROFILEOLD-P0005;PROFILEOLD-P0006;PROFILEOLD-P0007;PROFILEOLD-P0008;PROFILEOLD-P0009;PROFILEOLD-P0011;PROFILEOLD-P0015;PROFILEOLD-P0023;PROFILEOLD-P0031;PROFILEOLD-P0032;PROFILEOLD-P0033;PROFILEOLD-P0034;PROFILEOLD-P0035;PROFILEOLD-P0036;PROFILEOLD-P0038;PROFILEOLD-P0039;PROFILEOLD-P0040;PROFILEOLD-P0047;PROFILEOLD-P0048;PROFILEOLD-P0049;PROFILEOLD-P0050;PROFILEOLD-P0051;PROFILEOLD-P0052;PROFILEOLD-P0053;PROFILEOLD-P0055;PROFILEOLD-P0056;PROFILEOLD-P0057;PROFILEOLD-P0058;PROFILEOLD-P0059;PROFILEOLD-P0060;PROFILEOLD-P0061;PROFILEOLD-P0062;PROFILEOLD-P0063;PROFILEOLD-P0064;PROFILEOLD-P0065;PROFILEOLD-P0066;PROFILEOLD-P0067;PROFILEOLD-P0070;PROFILEOLD-P0071;PROFILEOLD-P0072;PROFILEOLD-P0073;PROFILEOLD-P0074;PROFILEOLD-P0075;PROFILEOLD-P0077;PROFILEOLD-P0079;PROFILEOLD-P0080;PROFILEOLD-P0081;PROFILEOLD-P0084;PROFILEOLD-P0085;PROFILEOLD-P0086;PROFILEOLD-P0087;PROFILEOLD-P0088;PROFILEOLD-P0089;PROFILEOLD-P0091;PROFILEOLD-P0093;PROFILEOLD-P0094;PROFILEOLD-P0095;PROFILEOLD-P0096;PROFILEOLD-P0098;PROFILEOLD-P0099;PROFILEOLD-P0100;PROFILEOLD-P0101;PROFILEOLD-P0102;PROFILEOLD-P0105;PROFILEOLD-P0106;PROFILEOLD-P0107;PROFILEOLD-P0108;PROFILEOLD-P0109;PROFILEOLD-P0110;PROFILEOLD-P0112;PROFILEOLD-P0113;PROFILEOLD-P0115;PROFILEOLD-P0116;PROFILEOLD-P0119;PROFILEOLD-P0120;PROFILEOLD-P0121;PROFILEOLD-P0122;PROFILEOLD-P0123;PROFILEOLD-P0124;PROFILEOLD-P0126;PROFILEOLD-P0127;PROFILEOLD-P0128;PROFILEOLD-P0129;PROFILEOLD-P0130;PROFILEOLD-P0131;PROFILEOLD-P0132;PROFILEOLD-P0133;PROFILEOLD-P0134;PROFILEOLD-P0135;PROFILEOLD-P0136;PROFILEOLD-P0137;PROFILEOLD-P0139;PROFILEOLD-P0142;PROFILEOLD-P0144;PROFILEOLD-P0146;PROFILEOLD-P0147;PROFILEOLD-P0148;PROFILEOLD-P0149;PROFILEOLD-P0151;PROFILEOLD-P0153;PROFILEOLD-P0158;PROFILEOLD-P0159;PROFILEOLD-P0160;PROFILEOLD-P0163;PROFILEOLD-P0164;PROFILEOLD-P0165;PROFILEOLD-P0166;PROFILEOLD-P0167;PROFILEOLD-P0168;PROFILEOLD-P0169;PROFILEOLD-P0170;PROFILEOLD-P0171;PROFILEOLD-P0172;PROFILEOLD-P0174;PROFILEOLD-P0177;PROFILEOLD-P0178;PROFILEOLD-P0179;PROFILEOLD-P0182;PROFILEOLD-P0184;PROFILEOLD-P0185;PROFILEOLD-P0187;PROFILEOLD-P0188;PROFILEOLD-P0189;PROFILEOLD-P0192;PROFILEOLD-P0193;PROFILEOLD-P0194;PROFILEOLD-P0195;PROFILEOLD-P0197;PROFILEOLD-P0199;PROFILEOLD-P0200;PROFILEOLD-P0202;PROFILEOLD-P0203;PROFILEOLD-P0204;PROFILEOLD-P0207;PROFILEOLD-P0209;PROFILEOLD-P0212;PROFILEOLD-P0213;PROFILEOLD-P0214;PROFILEOLD-P0215;PROFILEOLD-P0217;PROFILEOLD-P0219;PROFILEOLD-P0222;PROFILEOLD-P0224;PROFILEOLD-P0225;PROFILEOLD-P0227;PROFILEOLD-P0228;PROFILEOLD-P0229;PROFILEOLD-P0232;PROFILEOLD-P0237;PROFILEOLD-P0239;PROFILEOLD-P0241;PROFILEOLD-P0242;PROFILEOLD-P0243;PROFILEOLD-P0244;PROFILEOLD-P0246;PROFILEOLD-P0247;PROFILEOLD-P0250;PROFILEOLD-P0254;PROFILEOLD-P0255;PROFILEOLD-P0256;PROFILEOLD-P0257;PROFILEOLD-P0258;PROFILEOLD-P0266;PROFILEOLD-P0268;PROFILEOLD-P0270;PROFILEOLD-P0272;PROFILEOLD-P0273;PROFILEOLD-P0274;PROFILEOLD-P0276;PROFILEOLD-P0283;PROFILEOLD-P0284;PROFILEOLD-P0285;PROFILEOLD-P0286;PROFILEOLD-P0287;PROFILEOLD-P0289;PROFILEOLD-P0290;PROFILEOLD-P0292;PROFILEOLD-P0294;PROFILEOLD-P0296;PROFILEOLD-P0299;PROFILEOLD-P0300;PROFILEOLD-P0306;PROFILEOLD-P0307;PROFILEOLD-P0314;PROFILEOLD-P0319;PROFILEOLD-P0322;PROFILEOLD-P0323;PROFILEOLD-P0324;PROFILEOLD-P0326;PROFILEOLD-P0327;PROFILEOLD-P0328;PROFILEOLD-P0329;PROFILEOLD-P0331;PROFILEOLD-P0332;PROFILEOLD-P0333;PROFILEOLD-P0334;PROFILEOLD-P0335;PROFILEOLD-P0338;PROFILEOLD-P0342;PROFILEOLD-P0344;PROFILEOLD-P0347;PROFILEOLD-P0348;PROFILEOLD-P0350;PROFILEOLD-P0356;PROFILEOLD-P0359;PROFILEOLD-P0360;PROFILEOLD-P0361;PROFILEOLD-P0362;PROFILEOLD-P0363;PROFILEOLD-P0364;PROFILEOLD-P0470;PROFILEOLD-P0471,474,"[{""id"":""PROFILEV1-P0001"",""pedido"":""Gestor de Perfis e Acessos do Portal InvesteMoz — Versão Consolidada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 1 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0002"",""pedido"":""Especificação funcional, matriz de permissões, fluxos, controlos, critérios de aceitação e casos de teste — Versão 1.0 | 10 de outubro de 2026"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 2 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0003"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 3 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0005"",""pedido"":""Resumo executivo"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 5 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0007"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 7 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0008"",""pedido"":""Índice"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 8 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0009"",""pedido"":""Gestor de Perfis e Acessos do Portal InvesteMoz — Versão Consolidada1"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 9 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0010"",""pedido"":""Resumo executivo1"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 10 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0011"",""pedido"":""Índice2"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 11 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0012"",""pedido"":""1. Modelo de acesso recomendado3"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 12 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0013"",""pedido"":""2. Perfis obrigatórios3"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 13 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0014"",""pedido"":""3. Diagrama de permissões4"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 14 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0015"",""pedido"":""3.1 Diagrama de autorização por perfil4"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 15 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0016"",""pedido"":""3.2 Matriz detalhada de permissões4"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 16 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0017"",""pedido"":""3.3 Casos de uso por perfil6"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 17 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0018"",""pedido"":""3.4 Validação da matriz com cenários de acesso6"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 18 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0020"",""pedido"":""3.6 Regras de exceção e escalamento9"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 20 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0021"",""pedido"":""4. Cadastro e ciclo de vida10"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 21 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0022"",""pedido"":""5. Regras funcionais essenciais10"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 22 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0024"",""pedido"":""7. Modelo de dados mínimo11"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 24 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0025"",""pedido"":""8. Solução tecnológica recomendada12"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 25 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0026"",""pedido"":""9. Comparação com boas práticas da indústria12"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 26 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0027"",""pedido"":""10. Critérios mínimos de aceitação13"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 27 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0028"",""pedido"":""Anexo A — Casos de teste por perfil13"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 28 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0029"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 29 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0030"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 30 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0031"",""pedido"":""1. Modelo de acesso recomendado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 31 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0033"",""pedido"":""Adotar um modelo híbrido RBAC + ABAC: o RBAC atribui permissões por perfil; o ABAC aplica condições adicionais, como tipo de oportunidade, organização representada, província, estado do processo e propriedade do registo. As permissões devem ser associadas a papéis, nunca diretamente a utilizadores, salvo acessos temporários formalmente aprovados."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 33 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0034"",""pedido"":""2. Perfis obrigatórios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 34 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0035"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 35 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0036"",""pedido"":""Âmbito"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 36 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0037"",""pedido"":""Permissões principais"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 37 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0038"",""pedido"":""Restrições"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 38 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0039"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 39 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0040"",""pedido"":""Administração global"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 40 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0044"",""pedido"":""Consulta e interação pessoal"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 44 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0047"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 47 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0052"",""pedido"":""Verificação técnica"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 52 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0060"",""pedido"":""Consulta e controlo"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 60 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0061"",""pedido"":""Consultar configurações, histórico de acessos, alterações, decisões e relatórios de conformidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 61 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0062"",""pedido"":""Acesso apenas de leitura; sem alteração de dados operacionais."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 62 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0063"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 63 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0064"",""pedido"":""3. Diagrama de permissões"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 64 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0065"",""pedido"":""3.1 Diagrama de autorização por perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 65 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0067"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 67 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0068"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 68 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0069"",""pedido"":""Diagrama 1 — Fluxo de autorização por perfil e aplicação dos controlos transversais. O código pode ser copiado para qualquer renderizador compatível com Mermaid."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 69 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0070"",""pedido"":""3.2 Matriz detalhada de permissões"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 70 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0071"",""pedido"":""Recurso / ação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 71 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0072"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 72 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0074"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 74 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0078"",""pedido"":""Consultar oportunidades públicas"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 78 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0079"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 79 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0080"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 80 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0081"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 81 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0082"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 82 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0083"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 83 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0084"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 84 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0086"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 86 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0087"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 87 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0088"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 88 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0089"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 89 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0090"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 90 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0091"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 91 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0092"",""pedido"":""Gerir utilizadores e perfis"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 92 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0093"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 93 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0094"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 94 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0095"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 95 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0096"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 96 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0097"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 97 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0098"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 98 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0101"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 101 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0102"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 102 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0103"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 103 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0104"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 104 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0105"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 105 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0106"",""pedido"":""Criar oportunidade"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 106 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0108"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 108 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0110"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 110 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0111"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 111 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0112"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 112 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0115"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 115 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0116"",""pedido"":""Próprio"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 116 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0117"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 117 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0118"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 118 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0119"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 119 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0120"",""pedido"":""Submeter oportunidade"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 120 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0122"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 122 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0124"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 124 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0125"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 125 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0126"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 126 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0127"",""pedido"":""Anexar documentos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 127 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0129"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 129 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0130"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 130 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0131"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 131 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0132"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 132 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0133"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 133 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0136"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 136 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0137"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 137 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0138"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 138 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0139"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 139 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0140"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 140 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0141"",""pedido"":""Aprovar ou rejeitar tecnicamente"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 141 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0143"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 143 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0144"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 144 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0146"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 146 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0147"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 147 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0150"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 150 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0151"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 151 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0152"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 152 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0153"",""pedido"":""Validada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 153 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0154"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 154 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0155"",""pedido"":""Suspender ou arquivar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 155 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0157"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 157 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0158"",""pedido"":""Solicitar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 158 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0159"",""pedido"":""Recomendar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 159 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0160"",""pedido"":""Sim, com motivo"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 160 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0161"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 161 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0162"",""pedido"":""Gerir taxonomias e fluxos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 162 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0163"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 163 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0164"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 164 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0165"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 165 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0166"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 166 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0167"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 167 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0168"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 168 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0170"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 170 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0173"",""pedido"":""Âmbito de validação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 173 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0175"",""pedido"":""Total, somente leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 175 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0177"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 177 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0178"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 178 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0179"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 179 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0180"",""pedido"":""Validação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 180 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0182"",""pedido"":""Total, com proteção de dados"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 182 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0184"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 184 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0189"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 189 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0190"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 190 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0191"",""pedido"":""3.3 Casos de uso por perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 191 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0194"",""pedido"":""3.4 Validação da matriz com cenários de acesso"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 194 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0195"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 195 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0196"",""pedido"":""Cenário"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 196 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0197"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 197 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0198"",""pedido"":""Decisão"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 198 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0199"",""pedido"":""Regra validada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 199 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0200"",""pedido"":""AC-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 200 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0201"",""pedido"":""Consultar oportunidade publicada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 201 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0202"",""pedido"":""Todos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 202 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0203"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 203 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0205"",""pedido"":""AC-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 205 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0208"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 208 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0209"",""pedido"":""Apenas dados próprios; tentativa registada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 209 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0210"",""pedido"":""AC-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 210 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0212"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 212 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0213"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 213 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0215"",""pedido"":""AC-04"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 215 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0216"",""pedido"":""Criar oportunidade de tipo não autorizado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 216 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0217"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 217 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0218"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 218 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0219"",""pedido"":""ABAC bloqueia tipo fora da autorização."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 219 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0220"",""pedido"":""AC-05"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 220 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0222"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 222 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0223"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 223 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0224"",""pedido"":""Proteção contra acesso horizontal."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 224 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0225"",""pedido"":""AC-06"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 225 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0226"",""pedido"":""Aprovar oportunidade criada pelo próprio utilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 226 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0228"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 228 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0230"",""pedido"":""AC-07"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 230 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0231"",""pedido"":""Solicitar correção numa oportunidade submetida"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 231 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0233"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 233 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0234"",""pedido"":""Estado Submetida ou Em validação e âmbito válido."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 234 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0235"",""pedido"":""AC-08"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 235 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0238"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 238 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0240"",""pedido"":""AC-09"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 240 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0243"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 243 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0244"",""pedido"":""Transição de estado inválida."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 244 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0245"",""pedido"":""AC-10"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 245 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0246"",""pedido"":""Alterar conteúdo técnico aprovado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 246 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0248"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 248 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0250"",""pedido"":""AC-11"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 250 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0253"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 253 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0255"",""pedido"":""AC-12"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 255 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0256"",""pedido"":""Alterar uma configuração operacional"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 256 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0258"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 258 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0259"",""pedido"":""Perfil estritamente de leitura."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 259 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0260"",""pedido"":""AC-13"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 260 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0262"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 262 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0263"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 263 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0270"",""pedido"":""AC-15"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 270 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0272"",""pedido"":""Perfil privilegiado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 272 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0273"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 273 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0274"",""pedido"":""Autenticação reforçada obrigatória."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 274 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0275"",""pedido"":""AC-16"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 275 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0277"",""pedido"":""Qualquer perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 277 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0278"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 278 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0281"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 281 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0285"",""pedido"":""3.6 Regras de exceção e escalamento"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 285 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0286"",""pedido"":""Evento"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 286 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0287"",""pedido"":""Tratamento imediato"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 287 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0288"",""pedido"":""Escalamento"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 288 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0289"",""pedido"":""Registo obrigatório"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 289 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0297"",""pedido"":""Atribuições, recusas, indisponibilidade e tempos de espera."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 297 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0299"",""pedido"":""Bloquear decisão e remover o processo da fila do interveniente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 299 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0301"",""pedido"":""Tipo de conflito, declaração, reatribuição e decisor final."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 301 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0303"",""pedido"":""Suspender contagem operacional aplicável e marcar dependência externa."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 303 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0304"",""pedido"":""Responsável técnico ou jurídico após o prazo; gestão em risco crítico."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 304 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0305"",""pedido"":""Pedido, destinatário, prazo, lembretes, parecer e impacto."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 305 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0307"",""pedido"":""Permitir ciclos configuráveis e comparar versões."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 307 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0314"",""pedido"":""Rejeição contestada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 314 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0315"",""pedido"":""Receber recurso dentro do prazo sem alterar a decisão original."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 315 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0316"",""pedido"":""Encaminhar a instância distinta e sem conflito."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 316 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0317"",""pedido"":""Fundamento inicial, recurso, evidências, decisor e decisão final."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 317 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0318"",""pedido"":""Risco grave, ilegalidade ou suspeita de fraude"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 318 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0320"",""pedido"":""Gestão, conformidade e, quando aplicável, assessoria jurídica."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 320 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0321"",""pedido"":""Alerta, evidências, acessos, medidas cautelares e autorizações."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 321 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0323"",""pedido"":""Aplicar suspensão preventiva, preservar evidências e iniciar revisão urgente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 323 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0325"",""pedido"":""Origem, classificação, prazo, decisão de repor, corrigir ou arquivar."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 325 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0327"",""pedido"":""Notificar responsável atual e impedir encerramento silencioso."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 327 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0330"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 330 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0331"",""pedido"":""4. Cadastro e ciclo de vida"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 331 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0338"",""pedido"":""5. Regras funcionais essenciais"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 338 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0351"",""pedido"":""Separação clara entre autenticação, gestão de identidades, autorização e regras de negócio."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 351 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0354"",""pedido"":""7. Modelo de dados mínimo"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 354 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0355"",""pedido"":""Entidades recomendadas: users, profiles, roles, permissions, user_roles, role_permissions, organizations, organization_members, opportunities, opportunity_types, promoter_authorizations, access_requests, approval_steps, operational_parameter_versions, temporary_privilege_grants, conflicts_of_interest, correction_cycles, appeals, escalation_rules, incidents, sessions e audit_logs. Os papéis e os parâmetros operacionais devem ser versionados, e as respetivas atribuições ou versões devem conter estado, origem, aprovador, data de início e validade. Cada oportunidade deve conservar a versão dos parâmetros aplicável ao início do processo. As elevações temporárias, decisões de recurso, incidentes, conflitos e escalamentos devem manter relações com o utilizador, a oportunidade, o processo, a etapa, o motivo, o responsável e o registo de auditoria correspondente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 355 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0356"",""pedido"":""8. Solução tecnológica recomendada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 356 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0358"",""pedido"":""9. Comparação com boas práticas da indústria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 358 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0359"",""pedido"":""Prática"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 359 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0360"",""pedido"":""Proposta InvesteMoz"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 360 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0361"",""pedido"":""Avaliação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 361 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0363"",""pedido"":""Perfis recebem apenas permissões necessárias e condicionadas por contexto."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 363 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0364"",""pedido"":""Alinhado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 364 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0365"",""pedido"":""Separação entre autenticação e autorização"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 365 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0366"",""pedido"":""Identidade centralizada; decisões de negócio aplicadas pela plataforma."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 366 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0367"",""pedido"":""Alinhado e reduz acoplamento."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 367 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0370"",""pedido"":""Alinhado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 370 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0374"",""pedido"":""Identidade proporcional ao risco"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 374 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0376"",""pedido"":""Alinhado com abordagem baseada no risco."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 376 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0379"",""pedido"":""Alinhado; deve ser acompanhado por indicadores."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 379 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0380"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 380 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0382"",""pedido"":""10. Critérios mínimos de aceitação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 382 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0388"",""pedido"":""Todas as operações críticas ficam pesquisáveis por utilizador, recurso, ação e período."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 388 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0391"",""pedido"":""Anexo A — Casos de teste por perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 391 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0392"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 392 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0393"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 393 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0394"",""pedido"":""Pré-condição"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 394 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0395"",""pedido"":""Passos / ação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 395 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0396"",""pedido"":""Resultado esperado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 396 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0502"",""pedido"":""Casos adicionais do perfil Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 502 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0503"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 503 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0504"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 504 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0505"",""pedido"":""Pré-condição"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 505 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0506"",""pedido"":""Passos / ação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 506 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0507"",""pedido"":""Resultado esperado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 507 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0518"",""pedido"":""Caso adicional de governação dos parâmetros operacionais"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 518 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0519"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 519 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0520"",""pedido"":""Âmbito"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 520 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0521"",""pedido"":""Pré-condição"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 521 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0522"",""pedido"":""Passos / ação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 522 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0523"",""pedido"":""Resultado esperado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 523 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0529"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 529 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0530"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 530 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0001"",""pedido"":""Gestor de Perfis e Acessos do Portal InvesteMoz"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 1 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0003"",""pedido"":""1. Modelo de acesso recomendado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 3 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0004"",""pedido"":""Adotar um modelo híbrido RBAC + ABAC: o RBAC atribui permissões por perfil; o ABAC aplica condições adicionais, como tipo de oportunidade, organização representada, província, estado do processo e propriedade do registo. As permissões devem ser associadas a papéis, nunca diretamente a utilizadores, salvo acessos temporários formalmente aprovados."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 4 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0005"",""pedido"":""2. Perfis obrigatórios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 5 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0006"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 6 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0007"",""pedido"":""Âmbito"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 7 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0008"",""pedido"":""Permissões principais"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 8 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0009"",""pedido"":""Restrições"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 9 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0011"",""pedido"":""Administração global"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 11 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0015"",""pedido"":""Consulta e interação pessoal"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 15 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0023"",""pedido"":""Verificação técnica"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 23 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0031"",""pedido"":""Consulta e controlo"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 31 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0032"",""pedido"":""Consultar configurações, histórico de acessos, alterações, decisões e relatórios de conformidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 32 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0033"",""pedido"":""Acesso apenas de leitura; sem alteração de dados operacionais."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 33 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0034"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 34 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0035"",""pedido"":""3. Diagrama de permissões"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 35 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0036"",""pedido"":""3.1 Diagrama de autorização por perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 36 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0038"",""pedido"":""Diagrama 1 — Fluxo de autorização por perfil e aplicação dos controlos transversais. O código pode ser copiado para qualquer renderizador compatível com Mermaid."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 38 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0039"",""pedido"":""3.2 Matriz detalhada de permissões"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 39 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0040"",""pedido"":""Recurso / ação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 40 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0047"",""pedido"":""Consultar oportunidades públicas"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 47 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0048"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 48 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0049"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 49 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0050"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 50 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0051"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 51 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0052"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 52 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0053"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 53 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0055"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 55 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0056"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 56 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0057"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 57 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0058"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 58 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0059"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 59 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0060"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 60 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0061"",""pedido"":""Gerir utilizadores e perfis"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 61 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0062"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 62 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0063"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 63 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0064"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 64 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0065"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 65 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0066"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 66 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0067"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 67 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0070"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 70 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0071"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 71 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0072"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 72 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0073"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 73 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0074"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 74 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0075"",""pedido"":""Criar oportunidade"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 75 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0077"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 77 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0079"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 79 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0080"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 80 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0081"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 81 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0084"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 84 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0085"",""pedido"":""Próprio"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 85 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0086"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 86 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0087"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 87 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0088"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 88 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0089"",""pedido"":""Submeter oportunidade"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 89 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0091"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 91 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0093"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 93 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0094"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 94 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0095"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 95 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0096"",""pedido"":""Anexar documentos"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 96 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0098"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 98 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0099"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 99 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0100"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 100 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0101"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 101 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0102"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 102 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0105"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 105 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0106"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 106 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0107"",""pedido"":""Sim"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 107 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0108"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 108 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0109"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 109 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0110"",""pedido"":""Aprovar ou rejeitar tecnicamente"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 110 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0112"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 112 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0113"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 113 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0115"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 115 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0116"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 116 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0119"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 119 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0120"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 120 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0121"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 121 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0122"",""pedido"":""Validada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 122 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0123"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 123 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0124"",""pedido"":""Suspender ou arquivar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 124 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0126"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 126 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0127"",""pedido"":""Solicitar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 127 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0128"",""pedido"":""Recomendar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 128 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0129"",""pedido"":""Sim, com motivo"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 129 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0130"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 130 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0131"",""pedido"":""Gerir taxonomias e fluxos"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 131 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0132"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 132 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0133"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 133 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0134"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 134 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0135"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 135 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0136"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 136 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0137"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 137 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0139"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 139 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0142"",""pedido"":""Âmbito de validação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 142 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0144"",""pedido"":""Total, somente leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 144 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0146"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 146 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0147"",""pedido"":""Não"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 147 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0148"",""pedido"":""Próprios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 148 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0149"",""pedido"":""Validação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 149 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0151"",""pedido"":""Total, com proteção de dados"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 151 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0153"",""pedido"":""Total"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 153 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0158"",""pedido"":""Leitura"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 158 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0159"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 159 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0160"",""pedido"":""3.3 Casos de uso por perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 160 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0163"",""pedido"":""3.4 Validação da matriz com cenários de acesso"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 163 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0164"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 164 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0165"",""pedido"":""Cenário"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 165 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0166"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 166 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0167"",""pedido"":""Decisão"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 167 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0168"",""pedido"":""Regra validada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 168 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0169"",""pedido"":""AC-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 169 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0170"",""pedido"":""Consultar oportunidade publicada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 170 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0171"",""pedido"":""Todos"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 171 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0172"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 172 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0174"",""pedido"":""AC-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 174 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0177"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 177 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0178"",""pedido"":""Apenas dados próprios; tentativa registada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 178 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0179"",""pedido"":""AC-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 179 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0182"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 182 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0184"",""pedido"":""AC-04"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 184 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0185"",""pedido"":""Criar oportunidade de tipo não autorizado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 185 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0187"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 187 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0188"",""pedido"":""ABAC bloqueia tipo fora da autorização."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 188 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0189"",""pedido"":""AC-05"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 189 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0192"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 192 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0193"",""pedido"":""Proteção contra acesso horizontal."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 193 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0194"",""pedido"":""AC-06"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 194 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0195"",""pedido"":""Aprovar oportunidade criada pelo próprio utilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 195 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0197"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 197 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0199"",""pedido"":""AC-07"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 199 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0200"",""pedido"":""Solicitar correção numa oportunidade submetida"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 200 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0202"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 202 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0203"",""pedido"":""Estado Submetida ou Em validação e âmbito válido."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 203 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0204"",""pedido"":""AC-08"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 204 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0207"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 207 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0209"",""pedido"":""AC-09"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 209 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0212"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 212 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0213"",""pedido"":""Transição de estado inválida."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 213 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0214"",""pedido"":""AC-10"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 214 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0215"",""pedido"":""Alterar conteúdo técnico aprovado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 215 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0217"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 217 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0219"",""pedido"":""AC-11"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 219 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0222"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 222 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0224"",""pedido"":""AC-12"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 224 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0225"",""pedido"":""Alterar uma configuração operacional"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 225 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0227"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 227 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0228"",""pedido"":""Perfil estritamente de leitura."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 228 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0229"",""pedido"":""AC-13"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 229 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0232"",""pedido"":""Permitir"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 232 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0237"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 237 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0239"",""pedido"":""AC-15"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 239 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0241"",""pedido"":""Perfil privilegiado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 241 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0242"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 242 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0243"",""pedido"":""Autenticação reforçada obrigatória."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 243 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0244"",""pedido"":""AC-16"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 244 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0246"",""pedido"":""Qualquer perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 246 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0247"",""pedido"":""Negar"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 247 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0250"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 250 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0254"",""pedido"":""3.6 Regras de exceção e escalamento"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 254 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0255"",""pedido"":""Evento"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 255 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0256"",""pedido"":""Tratamento imediato"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 256 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0257"",""pedido"":""Escalamento"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 257 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0258"",""pedido"":""Registo obrigatório"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 258 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0266"",""pedido"":""Atribuições, recusas, indisponibilidade e tempos de espera."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 266 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0268"",""pedido"":""Bloquear decisão e remover o processo da fila do interveniente."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 268 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0270"",""pedido"":""Tipo de conflito, declaração, reatribuição e decisor final."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 270 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0272"",""pedido"":""Suspender contagem operacional aplicável e marcar dependência externa."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 272 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0273"",""pedido"":""Responsável técnico ou jurídico após o prazo; gestão em risco crítico."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 273 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0274"",""pedido"":""Pedido, destinatário, prazo, lembretes, parecer e impacto."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 274 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0276"",""pedido"":""Permitir ciclos configuráveis e comparar versões."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 276 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0283"",""pedido"":""Rejeição contestada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 283 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0284"",""pedido"":""Receber recurso dentro do prazo sem alterar a decisão original."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 284 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0285"",""pedido"":""Encaminhar a instância distinta e sem conflito."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 285 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0286"",""pedido"":""Fundamento inicial, recurso, evidências, decisor e decisão final."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 286 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0287"",""pedido"":""Risco grave, ilegalidade ou suspeita de fraude"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 287 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0289"",""pedido"":""Gestão, conformidade e, quando aplicável, assessoria jurídica."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 289 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0290"",""pedido"":""Alerta, evidências, acessos, medidas cautelares e autorizações."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 290 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0292"",""pedido"":""Aplicar suspensão preventiva, preservar evidências e iniciar revisão urgente."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 292 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0294"",""pedido"":""Origem, classificação, prazo, decisão de repor, corrigir ou arquivar."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 294 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0296"",""pedido"":""Notificar responsável atual e impedir encerramento silencioso."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 296 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0299"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 299 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0300"",""pedido"":""4. Cadastro e ciclo de vida"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 300 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0306"",""pedido"":""5. Regras funcionais essenciais"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 306 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0307"",""pedido"":""Uma conta pode ter vários perfis, mas as permissões efetivas resultam da união controlada dos papéis e das restrições aplicáveis."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 307 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0314"",""pedido"":""Todos os eventos relevantes devem registar utilizador, data e hora, endereço de origem, ação, objeto afetado, valores anteriores e novos e justificativo."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 314 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0319"",""pedido"":""Separação clara entre autenticação, gestão de identidades, autorização e regras de negócio."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 319 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0322"",""pedido"":""7. Modelo de dados mínimo"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 322 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0323"",""pedido"":""Entidades recomendadas: users, profiles, roles, permissions, user_roles, role_permissions, organizations, organization_members, opportunity_types, promoter_authorizations, access_requests, approval_steps, sessions e audit_logs. Os papéis devem ser versionados e as atribuições devem conter estado, origem, aprovador, data de início e validade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 323 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0324"",""pedido"":""8. Solução tecnológica recomendada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 324 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0326"",""pedido"":""9. Comparação com boas práticas da indústria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 326 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0327"",""pedido"":""Prática"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 327 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0328"",""pedido"":""Proposta InvesteMoz"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 328 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0329"",""pedido"":""Avaliação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 329 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0331"",""pedido"":""Perfis recebem apenas permissões necessárias e condicionadas por contexto."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 331 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0332"",""pedido"":""Alinhado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 332 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0333"",""pedido"":""Separação entre autenticação e autorização"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 333 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0334"",""pedido"":""Identidade centralizada; decisões de negócio aplicadas pela plataforma."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 334 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0335"",""pedido"":""Alinhado e reduz acoplamento."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 335 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0338"",""pedido"":""Alinhado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 338 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0342"",""pedido"":""Identidade proporcional ao risco"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 342 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0344"",""pedido"":""Alinhado com abordagem baseada no risco."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 344 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0347"",""pedido"":""Alinhado; deve ser acompanhado por indicadores."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 347 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0348"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 348 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0350"",""pedido"":""10. Critérios mínimos de aceitação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 350 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0356"",""pedido"":""Todas as operações críticas ficam pesquisáveis por utilizador, recurso, ação e período."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 356 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0359"",""pedido"":""11. Casos de teste por perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 359 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0360"",""pedido"":""ID"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 360 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0361"",""pedido"":""Perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 361 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0362"",""pedido"":""Pré-condição"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 362 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0363"",""pedido"":""Passos / ação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 363 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0364"",""pedido"":""Resultado esperado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 364 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0470"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 470 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0471"",""pedido"":"""",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 471 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",Doze atores normais MFA e consultas por perfil no servidor QA; schema ligado às entidades canónicas.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-02,"Utilizador público: consulta, favoritos/alertas e pedidos próprios","Gestao de perfis investeMOZ v1.docx | parágrafo 43 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 73 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 204 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 207 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 329 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 332 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 383 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 412 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 413 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 414 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 415 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 416 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 417 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 418 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 419 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 420 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 421 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 422 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 423 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 424 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 425 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 426 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 14 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 42 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 173 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 176 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 298 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 301 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 351 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 380 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 381 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 382 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 383 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 384 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 385 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 386 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 387 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 388 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 389 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 390 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 391 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 392 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 393 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 394 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,Capacidades públicas existentes; pedido próprio de Promotor reutiliza conta verificada.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"Conta20: dashboard→pedido, criação403 e consulta de pedido alheio403; favoritos/alertas não ensaiados neste lote. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"Demonstrar favoritos/alertas e todos os pedidos pessoais na interface; alternativa de confirmação por telefone da v1 ainda não implementada, verificação de email existente preservada.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0043;PROFILEV1-P0073;PROFILEV1-P0204;PROFILEV1-P0207;PROFILEV1-P0329;PROFILEV1-P0332;PROFILEV1-P0383;PROFILEV1-P0412;PROFILEV1-P0413;PROFILEV1-P0414;PROFILEV1-P0415;PROFILEV1-P0416;PROFILEV1-P0417;PROFILEV1-P0418;PROFILEV1-P0419;PROFILEV1-P0420;PROFILEV1-P0421;PROFILEV1-P0422;PROFILEV1-P0423;PROFILEV1-P0424;PROFILEV1-P0425;PROFILEV1-P0426;PROFILEOLD-P0014;PROFILEOLD-P0042;PROFILEOLD-P0173;PROFILEOLD-P0176;PROFILEOLD-P0298;PROFILEOLD-P0301;PROFILEOLD-P0351;PROFILEOLD-P0380;PROFILEOLD-P0381;PROFILEOLD-P0382;PROFILEOLD-P0383;PROFILEOLD-P0384;PROFILEOLD-P0385;PROFILEOLD-P0386;PROFILEOLD-P0387;PROFILEOLD-P0388;PROFILEOLD-P0389;PROFILEOLD-P0390;PROFILEOLD-P0391;PROFILEOLD-P0392;PROFILEOLD-P0393;PROFILEOLD-P0394,44,"[{""id"":""PROFILEV1-P0043"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 43 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0073"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 73 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0204"",""pedido"":""Recurso público disponível a todos os perfis."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 204 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0207"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 207 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0329"",""pedido"":""Tempo por etapa, alertas, justificações e ação de cada nível."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 329 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0332"",""pedido"":""Conta pública: após confirmação do correio eletrónico ou telefone, o utilizador recebe automaticamente o perfil “Utilizador público”."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 332 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0383"",""pedido"":""Uma nova conta recebe automaticamente apenas o perfil de Utilizador público."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 383 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0412"",""pedido"":""TC-UP-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 412 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0413"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 413 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0414"",""pedido"":""Conta confirmada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 414 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0415"",""pedido"":""Pesquisar, guardar favorito e subscrever alerta."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 415 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0416"",""pedido"":""Ações concluídas apenas na conta própria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 416 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0417"",""pedido"":""TC-UP-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 417 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0418"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 418 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0419"",""pedido"":""Conta autenticada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 419 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0420"",""pedido"":""Tentar abrir edição de oportunidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 420 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0421"",""pedido"":""Acesso negado; nenhuma alteração realizada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 421 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0422"",""pedido"":""TC-UP-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 422 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0423"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 423 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0424"",""pedido"":""Dois utilizadores existentes"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 424 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0425"",""pedido"":""Alterar o identificador do pedido para consultar pedido alheio."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 425 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0426"",""pedido"":""Acesso negado e tentativa registada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 426 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0014"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 14 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0042"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 42 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0173"",""pedido"":""Recurso público disponível a todos os perfis."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 173 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0176"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 176 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0298"",""pedido"":""Tempo por etapa, alertas, justificações e ação de cada nível."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 298 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0301"",""pedido"":""Conta pública: após confirmação do correio eletrónico ou telefone, o utilizador recebe automaticamente o perfil “Utilizador público”."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 301 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0351"",""pedido"":""Uma nova conta recebe automaticamente apenas o perfil de Utilizador público."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 351 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0380"",""pedido"":""TC-UP-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 380 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0381"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 381 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0382"",""pedido"":""Conta confirmada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 382 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0383"",""pedido"":""Pesquisar, guardar favorito e subscrever alerta."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 383 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0384"",""pedido"":""Ações concluídas apenas na conta própria."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 384 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0385"",""pedido"":""TC-UP-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 385 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0386"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 386 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0387"",""pedido"":""Conta autenticada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 387 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0388"",""pedido"":""Tentar abrir edição de oportunidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 388 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0389"",""pedido"":""Acesso negado; nenhuma alteração realizada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 389 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0390"",""pedido"":""TC-UP-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 390 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0391"",""pedido"":""Utilizador público"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 391 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0392"",""pedido"":""Dois utilizadores existentes"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 392 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0393"",""pedido"":""Alterar o identificador do pedido para consultar pedido alheio."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 393 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0394"",""pedido"":""Acesso negado e tentativa registada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 394 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","Conta20: dashboard→pedido, criação403 e consulta de pedido alheio403; favoritos/alertas não ensaiados neste lote.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-03,"Solicitar perfil de Promotor com representação, tipos e comprovativos","Gestao de perfis investeMOZ v1.docx | parágrafo 333 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 302 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"PortalProfileAdministration::request; documentos canónicos próprios/hash/scan, chave idempotente, âmbito individual ou organização representada.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"Contas21/22/23/31: quatro pedidos, replay sem duplicação, recuperação noutra sessão, quatro comprovativos sintéticos com ClamD real e recuperação por hash. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"Verificação visual do formulário, submissão de tipos adicionais e regras institucionais de comprovativos por representação.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.","Pedido guarda representação/tipos/comprovativos, fica recuperável e não concede o papel por si só.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0333;PROFILEOLD-P0302,2,"[{""id"":""PROFILEV1-P0333"",""pedido"":""Pedido de perfil Promotor: o utilizador informa se representa pessoa singular, empresa, entidade pública, associação ou parceiro; seleciona os tipos de oportunidade pretendidos e submete os comprovativos exigidos."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 333 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Pedido guarda representação/tipos/comprovativos, fica recuperável e não concede o papel por si só."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0302"",""pedido"":""Pedido de perfil Promotor: o utilizador informa se representa pessoa singular, empresa, entidade pública, associação ou parceiro; seleciona os tipos de oportunidade pretendidos e submete os comprovativos exigidos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 302 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Pedido guarda representação/tipos/comprovativos, fica recuperável e não concede o papel por si só."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","Contas21/22/23/31: quatro pedidos, replay sem duplicação, recuperação noutra sessão, quatro comprovativos sintéticos com ClamD real e recuperação por hash.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-04,Decisão independente do pedido de Promotor e tipos aprovados,"Gestao de perfis investeMOZ v1.docx | parágrafo 334 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 303 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Fila administrativa, consulta privada dos comprovativos por VerifiedDocumentBinary, versão e atestações auditadas; sem autoaprovação.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Super27 consulta originais por hash e aprova quatro pedidos de outros atores; teste nega decisão própria e regista rejeição com verificações falsas sem inventar confirmação. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,"Aceitação visual da fila e decisões; não foram validadas identidades reais, apenas documentos sintéticos QA.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Somente aprovador distinto com MFA confirma identidade/representação/documentos e concede os tipos efetivamente pedidos e aprovados.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0334;PROFILEOLD-P0303,2,"[{""id"":""PROFILEV1-P0334"",""pedido"":""Verificação: um responsável valida identidade, organização, representação e documentação. O sistema impede que o requerente aprove o próprio pedido."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 334 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Somente aprovador distinto com MFA confirma identidade/representação/documentos e concede os tipos efetivamente pedidos e aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0303"",""pedido"":""Verificação: um responsável valida identidade, organização, representação e documentação. O sistema impede que o requerente aprove o próprio pedido."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 303 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Somente aprovador distinto com MFA confirma identidade/representação/documentos e concede os tipos efetivamente pedidos e aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",Super27 consulta originais por hash e aprova quatro pedidos de outros atores; teste nega decisão própria e regista rejeição com verificações falsas sem inventar confirmação.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-05,Navegação por perfil a partir do dashboard,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,ProfileNavigation e props de autorização partilhadas; páginas existentes reutilizadas em /minhas-oportunidades.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"DashboardHTTP21 devolve Minhas oportunidades/Nova oportunidade;20 devolve Solicitar perfil; ensaio segue os URLs devolvidos, sem depender de rota conhecida previamente. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"Cliques, renderização, responsividade e resultado visível no navegador; C37 não fechado.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Promotor autorizado descobre lista/criação no dashboard; os outros descobrem pedido e acompanhamento sem obter criação.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-05-USER-20261010,1,"[{""id"":""AUD-PROFILE-05-USER-20261010"",""pedido"":""Navegação por perfil a partir do dashboard"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Promotor autorizado descobre lista/criação no dashboard; os outros descobrem pedido e acompanhamento sem obter criação."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","DashboardHTTP21 devolve Minhas oportunidades/Nova oportunidade;20 devolve Solicitar perfil; ensaio segue os URLs devolvidos, sem depender de rota conhecida previamente.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-06,Edição organizacional por outros Promotores e âmbito pessoal exclusivo,"Gestao de perfis investeMOZ v1.docx | parágrafo 49 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 109 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 214 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 221 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 340 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 371 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 372 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 385 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 437 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 438 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 439 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 440 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 441 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 20 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 78 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 183 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 190 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 308 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 339 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 340 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 353 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 405 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 407 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 408 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 409 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"OpportunityManagement/Resources reutilizados; owner_user_id preservado, contributors e membership de escrita em servidor.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"Autor21 cria oportunidade15; colega22 autorizado edita, recuperação mantémID/autor;23 fora da organização403. Seletores/mapas mudam para endpointsautorizadosv1:11províncias, seleçãoCaboDelgado gravada/recuperada noutra sessão com geometriaAPI. Teste de representação revogada nega escrita. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,Percurso visual e coedição dos recursos por operação; restrições provinciais permanecem separadas.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0049;PROFILEV1-P0109;PROFILEV1-P0214;PROFILEV1-P0221;PROFILEV1-P0340;PROFILEV1-P0371;PROFILEV1-P0372;PROFILEV1-P0385;PROFILEV1-P0437;PROFILEV1-P0438;PROFILEV1-P0439;PROFILEV1-P0440;PROFILEV1-P0441;PROFILEOLD-P0020;PROFILEOLD-P0078;PROFILEOLD-P0183;PROFILEOLD-P0190;PROFILEOLD-P0308;PROFILEOLD-P0339;PROFILEOLD-P0340;PROFILEOLD-P0353;PROFILEOLD-P0405;PROFILEOLD-P0407;PROFILEOLD-P0408;PROFILEOLD-P0409,25,"[{""id"":""PROFILEV1-P0049"",""pedido"":""Criar, guardar rascunhos, submeter e atualizar oportunidades da organização que representa; anexar documentos; responder a pedidos de correção."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 49 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0109"",""pedido"":""Organização e tipos autorizados"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 109 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0214"",""pedido"":""Propriedade, organização e tipo válidos."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 214 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0221"",""pedido"":""Editar oportunidade de outra organização por identificador direto"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 221 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0340"",""pedido"":""O Promotor só visualiza e altera oportunidades da organização que representa."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 340 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0371"",""pedido"":""Autorização por recurso e propriedade"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 371 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0372"",""pedido"":""Promotor limitado à sua organização, aos seus registos e aos tipos aprovados."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 372 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0385"",""pedido"":""Um Promotor não consegue consultar, editar ou eliminar oportunidades de outra organização."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 385 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0437"",""pedido"":""TC-PR-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 437 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0438"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 438 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0439"",""pedido"":""Oportunidade de outra organização"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 439 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0440"",""pedido"":""Tentar editar por URL ou identificador direto."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 440 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0441"",""pedido"":""Acesso negado sem exposição de dados."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 441 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0020"",""pedido"":""Criar, guardar rascunhos, submeter e atualizar oportunidades da organização que representa; anexar documentos; responder a pedidos de correção."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 20 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0078"",""pedido"":""Organização e tipos autorizados"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 78 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0183"",""pedido"":""Propriedade, organização e tipo válidos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 183 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0190"",""pedido"":""Editar oportunidade de outra organização por identificador direto"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 190 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0308"",""pedido"":""O Promotor só visualiza e altera oportunidades da organização que representa."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 308 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0339"",""pedido"":""Autorização por recurso e propriedade"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 339 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0340"",""pedido"":""Promotor limitado à sua organização, aos seus registos e aos tipos aprovados."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 340 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0353"",""pedido"":""Um Promotor não consegue consultar, editar ou eliminar oportunidades de outra organização."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 353 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0405"",""pedido"":""TC-PR-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 405 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0407"",""pedido"":""Oportunidade de outra organização"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 407 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0408"",""pedido"":""Tentar editar por URL ou identificador direto."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 408 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0409"",""pedido"":""Acesso negado sem exposição de dados."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 409 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","Autor21 cria oportunidade15; colega22 autorizado edita, recuperação mantémID/autor;23 fora da organização403. Seletores/mapas mudam para endpointsautorizadosv1:11províncias, seleçãoCaboDelgado gravada/recuperada noutra sessão com geometriaAPI. Teste de representação revogada nega escrita.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-07,Autorizações por tipo e representação sem transferência silenciosa,"Gestao de perfis investeMOZ v1.docx | parágrafo 335 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 349 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 432 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 433 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 434 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 435 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 436 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 304 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 317 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 400 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 402 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 403 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 404 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Tipos em atribuições e pedidos; organização imutável na edição, autor/workflow/status proibidos no payload.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,HTTP22: mudança para tipo não aprovado403 e transferência de organização403; fixture testa isolamento de tipos. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,Demonstrar todos os contratos especializados e seus campos/validadores; seleção do tipo não os encerra.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0335;PROFILEV1-P0349;PROFILEV1-P0432;PROFILEV1-P0433;PROFILEV1-P0434;PROFILEV1-P0435;PROFILEV1-P0436;PROFILEOLD-P0304;PROFILEOLD-P0317;PROFILEOLD-P0400;PROFILEOLD-P0402;PROFILEOLD-P0403;PROFILEOLD-P0404,13,"[{""id"":""PROFILEV1-P0335"",""pedido"":""Ativação condicionada: o perfil Promotor é ativado apenas para os tipos de oportunidade aprovados. Novos tipos exigem pedido adicional."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 335 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0349"",""pedido"":""Política de negar por defeito, verificação de autorização em cada pedido e proteção contra acesso horizontal a registos de terceiros."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 349 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0432"",""pedido"":""TC-PR-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 432 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0433"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 433 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0434"",""pedido"":""Tipo não autorizado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 434 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0435"",""pedido"":""Tentar criar oportunidade desse tipo."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 435 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0436"",""pedido"":""Operação bloqueada por política ABAC."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 436 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0304"",""pedido"":""Ativação condicionada: o perfil Promotor é ativado apenas para os tipos de oportunidade aprovados. Novos tipos exigem pedido adicional."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 304 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0317"",""pedido"":""Política de negar por defeito, verificação de autorização em cada pedido e proteção contra acesso horizontal a registos de terceiros."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 317 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0400"",""pedido"":""TC-PR-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 400 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0402"",""pedido"":""Tipo não autorizado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 402 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0403"",""pedido"":""Tentar criar oportunidade desse tipo."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 403 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0404"",""pedido"":""Operação bloqueada por política ABAC."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 404 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",HTTP22: mudança para tipo não aprovado403 e transferência de organização403; fixture testa isolamento de tipos.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-08,"Estados, razões, versões e dependências reais do workflow","Gestao de perfis investeMOZ v1.docx | parágrafo 113 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 342 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 343 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 82 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 310 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 311 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"OpportunityProfileWorkflow reutiliza códigos/management_version/etag/audit_events; revisão, correção, parecer, rejeição/suspensão/arquivo e pedidos segregados. | [Workflow QA 10/10/2026] Estados privados/versionados separados do estado publicado, conteúdo/recursos bloqueados após submissão; revisões/decisões por hash e histórico.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","HTTP: pedido de arquivo guarda e mantémdraft, submissão422 com lacuna explícita; fixture submetida inicia revisão, pede correção e recupera edição. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Ciclo positivo realHTTP com contas distintas; correção/resubmissão, aprovação/pub, recuperação, revisão material, preservação pública e suspensão demonstradas. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,"Submissão completa, aprovação/publicação, incidentes e conservação de versão pública ainda não demonstradas; fixture não é submissão real. | [Workflow QA 10/10/2026] Interface/C37; incidentes/opiniões completos, agendamento e revisão periódica, contratos/editores restantes; estados legados preservados.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0113;PROFILEV1-P0342;PROFILEV1-P0343;PROFILEOLD-P0082;PROFILEOLD-P0310;PROFILEOLD-P0311,6,"[{""id"":""PROFILEV1-P0113"",""pedido"":""Editar rascunho"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 113 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0342"",""pedido"":""Estados mínimos do processo: Rascunho, Submetida, Em validação, Pendente de parecer, Correção solicitada, Aprovada, Rejeitada, Publicada, Suspensa e Arquivada. O estado Encerrada aplica-se ao processo administrativo após rejeição definitiva, desistência, cancelamento ou conclusão sem possibilidade de nova ação operacional."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 342 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0343"",""pedido"":""Rejeições, suspensões e alterações de perfil exigem motivo obrigatório."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 343 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0082"",""pedido"":""Editar rascunho"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 82 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0310"",""pedido"":""Estados mínimos: Rascunho, Submetida, Em validação, Pendente de parecer, Correção solicitada, Aprovada, Rejeitada, Publicada, Suspensa, Arquivada e Encerrada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 310 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0311"",""pedido"":""Rejeições, suspensões e alterações de perfil exigem motivo obrigatório."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 311 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.","HTTP: pedido de arquivo guarda e mantémdraft, submissão422 com lacuna explícita; fixture submetida inicia revisão, pede correção e recupera edição. | [Workflow QA 10/10/2026] Ciclo positivo realHTTP com contas distintas; correção/resubmissão, aprovação/pub, recuperação, revisão material, preservação pública e suspensão demonstradas.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-09,"Impedir aprovação própria, conflitos de organização e publicação pelo aprovador","Gestao de perfis investeMOZ v1.docx | parágrafo 4 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 48 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 50 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 123 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 145 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 171 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 172 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 185 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 186 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 187 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 188 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 211 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 229 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 280 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 298 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 368 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 457 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 458 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 459 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 460 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 461 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 2 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 19 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 21 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 92 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 114 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 140 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 141 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 154 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 155 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 156 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 157 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 180 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 198 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 249 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 267 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 336 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 425 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 427 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 428 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 429 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Autor, contributors e membership da organização impedem revisão; publicação verifica aprovador da mesma versão; autorizações rechecadas sob lock. | [Workflow QA 10/10/2026] Independência verificada sob lock:autor/contribuinte/membroorg não valida; aprovador não publica; revisores e aprovador são reavaliados perante revogação/conflito.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","Teste autor com Promotor+Validador+Publicador continua403; regras editor/representação verificadas no serviço. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] HTTP403 autor21 comProm+Val+Pub, aprovador24 comVal+Pub, organização/múltiplos papéis31; MFA normal. Histórico das3atribuições temporárias/revogações preservado. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,Publicação real permanece bloqueada pelo contrato; testar ciclo completo e reatribuição independente com versão aprovada real. | [Workflow QA 10/10/2026] Visual dos controlos/negativas; segregações adicionais por perfil modular e gates de instância externa.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0004;PROFILEV1-P0048;PROFILEV1-P0050;PROFILEV1-P0123;PROFILEV1-P0145;PROFILEV1-P0171;PROFILEV1-P0172;PROFILEV1-P0185;PROFILEV1-P0186;PROFILEV1-P0187;PROFILEV1-P0188;PROFILEV1-P0211;PROFILEV1-P0229;PROFILEV1-P0280;PROFILEV1-P0298;PROFILEV1-P0368;PROFILEV1-P0457;PROFILEV1-P0458;PROFILEV1-P0459;PROFILEV1-P0460;PROFILEV1-P0461;PROFILEOLD-P0002;PROFILEOLD-P0019;PROFILEOLD-P0021;PROFILEOLD-P0092;PROFILEOLD-P0114;PROFILEOLD-P0140;PROFILEOLD-P0141;PROFILEOLD-P0154;PROFILEOLD-P0155;PROFILEOLD-P0156;PROFILEOLD-P0157;PROFILEOLD-P0180;PROFILEOLD-P0198;PROFILEOLD-P0249;PROFILEOLD-P0267;PROFILEOLD-P0336;PROFILEOLD-P0425;PROFILEOLD-P0427;PROFILEOLD-P0428;PROFILEOLD-P0429,41,"[{""id"":""PROFILEV1-P0004"",""pedido"":""Objetivo. Implementar um gestor centralizado de identidades, perfis, papéis e permissões que assegure acesso simples para o público, autonomia controlada para promotores e administração global controlada para utilizadores privilegiados, com rastreabilidade, segregação de funções, elevação temporária para ações operacionais e aplicação do princípio do menor privilégio."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 4 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0048"",""pedido"":""Gestão de oportunidades próprias"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 48 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0050"",""pedido"":""Atuação limitada aos tipos de oportunidade autorizados no cadastro e aos registos da própria organização; publicação sujeita a validação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 50 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0123"",""pedido"":""Própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 123 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0145"",""pedido"":""Sim, exceto criação própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 145 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0171"",""pedido"":""Apenas atividade própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 171 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0172"",""pedido"":""Apenas atividade própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 172 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0185"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 185 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0186"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 186 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0187"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 187 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0188"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 188 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0211"",""pedido"":""Criar oportunidade de tipo autorizado para a própria organização"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 211 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0229"",""pedido"":""Segregação de funções e conflito de interesse."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 229 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0280"",""pedido"":""Resultado da validação: os cenários AC-01 a AC-16 confirmam a coerência da matriz com o menor privilégio, a propriedade do recurso, a segregação de funções e as transições de estado. Estes cenários validam decisões de autorização; o Anexo A contém os casos de teste executáveis, evitando sobreposição de finalidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 280 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0298"",""pedido"":""Conflito de interesse"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 298 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0368"",""pedido"":""Segregação de funções"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 368 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0457"",""pedido"":""TC-VA-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 457 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0458"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 458 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0459"",""pedido"":""Validador é também criador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 459 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0460"",""pedido"":""Tentar aprovar a própria oportunidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 460 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0461"",""pedido"":""Operação bloqueada e processo encaminhado para reatribuição."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 461 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0002"",""pedido"":""Objetivo. Implementar um gestor centralizado de identidades, perfis, papéis e permissões que assegure acesso simples para o público, autonomia controlada para promotores e administração integral para utilizadores privilegiados, com rastreabilidade, segregação de funções e princípio do menor privilégio."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 2 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0019"",""pedido"":""Gestão de oportunidades próprias"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 19 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0021"",""pedido"":""Atuação limitada aos tipos de oportunidade autorizados no cadastro e aos registos da própria organização; publicação sujeita a validação."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 21 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0092"",""pedido"":""Própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 92 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0114"",""pedido"":""Sim, exceto criação própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 114 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0140"",""pedido"":""Apenas atividade própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 140 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0141"",""pedido"":""Apenas atividade própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 141 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0154"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 154 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0155"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 155 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0156"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 156 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0157"",""pedido"":""Conta própria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 157 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0180"",""pedido"":""Criar oportunidade de tipo autorizado para a própria organização"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 180 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0198"",""pedido"":""Segregação de funções e conflito de interesse."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 198 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0249"",""pedido"":""Resultado da validação: os cenários AC-01 a AC-16 confirmam a coerência da matriz com o menor privilégio, a propriedade do recurso, a segregação de funções e as transições de estado. Estes cenários validam decisões de autorização; a secção 11 contém os casos de teste executáveis, evitando sobreposição de finalidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 249 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0267"",""pedido"":""Conflito de interesse"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 267 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0336"",""pedido"":""Segregação de funções"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 336 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0425"",""pedido"":""TC-VA-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 425 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0427"",""pedido"":""Validador é também criador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 427 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0428"",""pedido"":""Tentar aprovar a própria oportunidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 428 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0429"",""pedido"":""Operação bloqueada e processo encaminhado para reatribuição."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 429 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.","Teste autor com Promotor+Validador+Publicador continua403; regras editor/representação verificadas no serviço. | [Workflow QA 10/10/2026] HTTP403 autor21 comProm+Val+Pub, aprovador24 comVal+Pub, organização/múltiplos papéis31; MFA normal. Histórico das3atribuições temporárias/revogações preservado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-10,Acumulação de papéis com negação prevalecente,"Gestao de perfis investeMOZ v1.docx | parágrafo 339 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 344 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 362 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 312 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 330 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Auditor nega escrita operacional; Super exige papel operacional mais elevação independente; papéis não se somam para ultrapassar restrições. | [Workflow QA 10/10/2026] Negação prevalece nos acessos diretos e transições, incluindo papéis acumulados e Auditor com escrita.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","Conta31 Promotor+Validador+Auditor lê e recebe403 na edição;27 Super sem Promotor/elevação recebe403 na criação. Fixture com papéis v1 e allowlist legada: criação fora do âmbito403, dashboard sem criação legada; Auditor nega escrita administrativa. Revogação/expiração não restaura permissão legada automaticamente. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] 403 nos percursos normais de MFA; temporárias revogadas, Promotor21 entra noutra sessão com o perfil original. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,Demonstração visual e combinações operacionais adicionais com elevação aprovada. | [Workflow QA 10/10/2026] Demonstração visual e políticas adicionais territoriais/perfis modulares.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.","A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0339;PROFILEV1-P0344;PROFILEV1-P0362;PROFILEOLD-P0312;PROFILEOLD-P0330,5,"[{""id"":""PROFILEV1-P0339"",""pedido"":""Uma conta pode ter vários perfis. As permissões efetivas resultam da união controlada das permissões concedidas, limitada pelas restrições aplicáveis; em caso de conflito, prevalecem a negação explícita, a segregação de funções e a condição mais restritiva."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 339 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0344"",""pedido"":""Permissões críticas não podem ser acumuladas quando houver conflito entre criação, validação, publicação e auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 344 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0362"",""pedido"":""Menor privilégio e negação por defeito"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 362 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0312"",""pedido"":""Permissões críticas não podem ser acumuladas quando houver conflito entre criação, validação, publicação e auditoria."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 312 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0330"",""pedido"":""Menor privilégio e negação por defeito"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 330 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.","Conta31 Promotor+Validador+Auditor lê e recebe403 na edição;27 Super sem Promotor/elevação recebe403 na criação. Fixture com papéis v1 e allowlist legada: criação fora do âmbito403, dashboard sem criação legada; Auditor nega escrita administrativa. Revogação/expiração não restaura permissão legada automaticamente. | [Workflow QA 10/10/2026] 403 nos percursos normais de MFA; temporárias revogadas, Promotor21 entra noutra sessão com o perfil original.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-11,"Validador: revisão atribuída, MFA, correções e decisão","Gestao de perfis investeMOZ v1.docx | parágrafo 19 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 51 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 53 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 54 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 58 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 75 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 134 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 227 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 232 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 239 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 249 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 282 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 294 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 295 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 306 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 384 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 442 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 443 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 444 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 445 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 446 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 447 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 448 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 449 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 450 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 451 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 452 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 453 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 454 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 455 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 456 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 462 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 463 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 464 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 465 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 466 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 18 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 22 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 24 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 25 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 29 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 43 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 44 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 103 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 181 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 186 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 191 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 196 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 201 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 208 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 218 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 251 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 263 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 264 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 275 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 352 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 396 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 401 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 406 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 410 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 411 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 412 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 413 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 414 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 415 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 416 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 417 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 418 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 419 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 420 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 421 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 422 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 423 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 424 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 426 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 430 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 431 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 432 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 433 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 434 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Papel validator com âmbito/tipos e responsabilidades compatíveis; MFA confirmado exigido na atribuição e recente na operação. | [Workflow QA 10/10/2026] Validador atribuível explícito, inicia revisão, solicita correção, rejeita com fundamento, regista gates aplicáveis e aprova versão completa. | [Semântica QA 10/10/2026] Validador atribuído e gates por competência; parecer técnico/jurídico exige destinatário independente com âmbito/MFA, resposta exclusiva dele, motivo/evidência e tarefa existente. Parecer não substitui aprovação do gate.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Semântica QA 10/10/2026] Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos.","24 aprovado inicialmente, aprovação de draft409, revogado depois; fixture independente revisa/corrige e recupera nova versão; semMFA403. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Validador24 fez o ciclo positivo; aprovação prematura422, motivo curto422, own403. Evidências apontam documentos desta oportunidade/versão. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.",parcial,"Fila de atribuição e completude normativa, decisão positiva integral e interface. | [Workflow QA 10/10/2026] Visual, distribuição/disponibilidade completa, revisões técnicas/jurídicas semânticas por todos os contratos e política SLA. | [Semântica QA 10/10/2026] Visual e responsabilidade institucional real; parecer externo/protocolos e disponibilidade completos. Gates sintéticos não são decisões jurídicas reais.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0019;PROFILEV1-P0051;PROFILEV1-P0053;PROFILEV1-P0054;PROFILEV1-P0058;PROFILEV1-P0075;PROFILEV1-P0134;PROFILEV1-P0227;PROFILEV1-P0232;PROFILEV1-P0239;PROFILEV1-P0249;PROFILEV1-P0282;PROFILEV1-P0294;PROFILEV1-P0295;PROFILEV1-P0306;PROFILEV1-P0384;PROFILEV1-P0442;PROFILEV1-P0443;PROFILEV1-P0444;PROFILEV1-P0445;PROFILEV1-P0446;PROFILEV1-P0447;PROFILEV1-P0448;PROFILEV1-P0449;PROFILEV1-P0450;PROFILEV1-P0451;PROFILEV1-P0452;PROFILEV1-P0453;PROFILEV1-P0454;PROFILEV1-P0455;PROFILEV1-P0456;PROFILEV1-P0462;PROFILEV1-P0463;PROFILEV1-P0464;PROFILEV1-P0465;PROFILEV1-P0466;PROFILEOLD-P0018;PROFILEOLD-P0022;PROFILEOLD-P0024;PROFILEOLD-P0025;PROFILEOLD-P0029;PROFILEOLD-P0043;PROFILEOLD-P0044;PROFILEOLD-P0103;PROFILEOLD-P0181;PROFILEOLD-P0186;PROFILEOLD-P0191;PROFILEOLD-P0196;PROFILEOLD-P0201;PROFILEOLD-P0208;PROFILEOLD-P0218;PROFILEOLD-P0251;PROFILEOLD-P0263;PROFILEOLD-P0264;PROFILEOLD-P0275;PROFILEOLD-P0352;PROFILEOLD-P0396;PROFILEOLD-P0401;PROFILEOLD-P0406;PROFILEOLD-P0410;PROFILEOLD-P0411;PROFILEOLD-P0412;PROFILEOLD-P0413;PROFILEOLD-P0414;PROFILEOLD-P0415;PROFILEOLD-P0416;PROFILEOLD-P0417;PROFILEOLD-P0418;PROFILEOLD-P0419;PROFILEOLD-P0420;PROFILEOLD-P0421;PROFILEOLD-P0422;PROFILEOLD-P0423;PROFILEOLD-P0424;PROFILEOLD-P0426;PROFILEOLD-P0430;PROFILEOLD-P0431;PROFILEOLD-P0432;PROFILEOLD-P0433;PROFILEOLD-P0434,80,"[{""id"":""PROFILEV1-P0019"",""pedido"":""3.5 Fluxos de aprovação, correção e rejeição7"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 19 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0051"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 51 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0053"",""pedido"":""Rever dados e documentos, solicitar correções, aprovar tecnicamente ou rejeitar com fundamentação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 53 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0054"",""pedido"":""Não deve publicar nem validar oportunidades por si criadas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 54 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0058"",""pedido"":""Não altera o conteúdo técnico aprovado sem devolver o processo ao promotor ou validador."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 58 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0075"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 75 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0134"",""pedido"":""Solicitar correções"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 134 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0227"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 227 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0232"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 232 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0239"",""pedido"":""Pré-condição de aprovação técnica satisfeita."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 239 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0249"",""pedido"":""Devolver ao Promotor ou Validador."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 249 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0282"",""pedido"":""3.5 Fluxos de aprovação, correção e rejeição"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 282 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0294"",""pedido"":""Validador indisponível"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 294 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0295"",""pedido"":""Redistribuir automaticamente para validador elegível."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 295 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0306"",""pedido"":""Correções repetidas"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 306 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0384"",""pedido"":""O perfil Promotor não é ativado sem validação documental e aprovação por utilizador distinto."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 384 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0442"",""pedido"":""TC-PR-04"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 442 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0443"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 443 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0444"",""pedido"":""Estado Correção solicitada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 444 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0445"",""pedido"":""Corrigir campos, substituir documento e voltar a submeter."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 445 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0446"",""pedido"":""Nova versão preservada; estado Submetida; histórico completo."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 446 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0447"",""pedido"":""TC-VA-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 447 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0448"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 448 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0449"",""pedido"":""Processo submetido e sem conflito"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 449 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0450"",""pedido"":""Rever e aprovar com comentário."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 450 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0451"",""pedido"":""Estado Aprovada; decisão, comentário e identidade registados."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 451 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0452"",""pedido"":""TC-VA-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 452 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0453"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 453 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0454"",""pedido"":""Processo incompleto"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 454 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0455"",""pedido"":""Solicitar correções com itens obrigatórios."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 455 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0456"",""pedido"":""Estado Correção solicitada; Promotor notificado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 456 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0462"",""pedido"":""TC-VA-04"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 462 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0463"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 463 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0464"",""pedido"":""Processo não conforme"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 464 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0465"",""pedido"":""Rejeitar sem fundamento e depois com fundamento."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 465 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0466"",""pedido"":""Primeira tentativa bloqueada; segunda aceite e estado Rejeitada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 466 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0018"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 18 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0022"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 22 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0024"",""pedido"":""Rever dados e documentos, solicitar correções, aprovar tecnicamente ou rejeitar com fundamentação."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 24 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0025"",""pedido"":""Não deve publicar nem validar oportunidades por si criadas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 25 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0029"",""pedido"":""Não altera o conteúdo técnico aprovado sem devolver o processo ao promotor ou validador."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 29 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0043"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 43 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0044"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 44 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0103"",""pedido"":""Solicitar correções"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 103 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0181"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 181 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0186"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 186 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0191"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 191 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0196"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 196 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0201"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 201 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0208"",""pedido"":""Pré-condição de aprovação técnica satisfeita."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 208 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0218"",""pedido"":""Devolver ao Promotor ou Validador."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 218 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0251"",""pedido"":""3.5 Fluxos de aprovação, correção e rejeição"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 251 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0263"",""pedido"":""Validador indisponível"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 263 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0264"",""pedido"":""Redistribuir automaticamente para validador elegível."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 264 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0275"",""pedido"":""Correções repetidas"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 275 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0352"",""pedido"":""O perfil Promotor não é ativado sem validação documental e aprovação por utilizador distinto."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 352 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0396"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 396 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0401"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 401 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0406"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 406 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0410"",""pedido"":""TC-PR-04"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 410 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0411"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 411 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0412"",""pedido"":""Estado Correção solicitada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 412 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0413"",""pedido"":""Corrigir campos, substituir documento e voltar a submeter."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 413 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0414"",""pedido"":""Nova versão preservada; estado Submetida; histórico completo."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 414 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0415"",""pedido"":""TC-VA-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 415 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0416"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 416 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0417"",""pedido"":""Processo submetido e sem conflito"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 417 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0418"",""pedido"":""Rever e aprovar com comentário."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 418 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0419"",""pedido"":""Estado Aprovada; decisão, comentário e identidade registados."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 419 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0420"",""pedido"":""TC-VA-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 420 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0421"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 421 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0422"",""pedido"":""Processo incompleto"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 422 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0423"",""pedido"":""Solicitar correções com itens obrigatórios."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 423 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0424"",""pedido"":""Estado Correção solicitada; Promotor notificado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 424 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0426"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 426 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0430"",""pedido"":""TC-VA-04"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 430 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0431"",""pedido"":""Validador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 431 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0432"",""pedido"":""Processo não conforme"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 432 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0433"",""pedido"":""Rejeitar sem fundamento e depois com fundamento."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 433 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0434"",""pedido"":""Primeira tentativa bloqueada; segunda aceite e estado Rejeitada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 434 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes.","24 aprovado inicialmente, aprovação de draft409, revogado depois; fixture independente revisa/corrige e recupera nova versão; semMFA403. | [Workflow QA 10/10/2026] Validador24 fez o ciclo positivo; aprovação prematura422, motivo curto422, own403. Evidências apontam documentos desta oportunidade/versão. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-12,"Publicador: versão aprovada, suspensão/arquivo e segregação","Gestao de perfis investeMOZ v1.docx | parágrafo 46 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 55 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 56 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 57 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 76 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 148 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 174 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 181 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 236 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 237 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 241 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 242 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 247 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 290 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 291 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 319 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 322 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 324 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 386 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 467 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 468 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 469 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 470 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 471 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 472 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 473 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 474 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 475 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 476 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 477 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 478 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 479 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 480 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 481 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 482 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 483 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 484 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 485 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 486 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 17 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 26 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 27 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 28 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 45 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 117 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 143 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 150 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 205 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 206 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 210 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 211 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 216 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 259 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 260 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 288 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 291 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 293 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 354 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 435 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 436 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 437 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 438 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 439 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 440 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 441 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 442 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 443 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 444 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 445 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 446 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 447 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 448 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 449 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 450 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 451 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 452 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 453 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 454 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Papel publisher, MFA recente, independência; conteúdo técnico não editável; publicar bloqueado se completude/versão faltam. | [Workflow QA 10/10/2026] Publicador independente confirma prévia/hash/âmbito, publica projeção mínima, suspende e arquiva; não edita dados técnicos. | [Semântica QA 10/10/2026] Publicação atribuível por publication_coordinator; assignee tem âmbito/MFA e é independente da autoria/aprovação. Publicador diverso403; prévia e projeção públicas do negócio usam apenas teaser autorizado.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Semântica QA 10/10/2026] Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos.","25 publica draft409; fixture confirma estado incompatível; todos os atos positivos de publicação integral continuam pendentes. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Publicador25:pub interna18; pública19 com2derivadas ClamD; confirmfalse422/hashdiverso409; alteração privada não vazou; suspensãoGETpúblico404. Fundiário20externapendente422. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.",parcial,"Publicação e agendamento, revisão de divulgação, suspensão urgente/retificação e prova da versão pública. | [Workflow QA 10/10/2026] Visual e cobertura editorial completa:imagens/mapas na ficha, tradução/NDA/teaser específico, agendamento, monitoria, coordenação editorial e reversão de edição publicada. | [Semântica QA 10/10/2026] Visual da prévia/imagem/mapa; agendamento/tradução/revisão periódica; DUAT comatoexternopendente não publicável; perfis/regras reais pendentes.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0046;PROFILEV1-P0055;PROFILEV1-P0056;PROFILEV1-P0057;PROFILEV1-P0076;PROFILEV1-P0148;PROFILEV1-P0174;PROFILEV1-P0181;PROFILEV1-P0236;PROFILEV1-P0237;PROFILEV1-P0241;PROFILEV1-P0242;PROFILEV1-P0247;PROFILEV1-P0290;PROFILEV1-P0291;PROFILEV1-P0319;PROFILEV1-P0322;PROFILEV1-P0324;PROFILEV1-P0386;PROFILEV1-P0467;PROFILEV1-P0468;PROFILEV1-P0469;PROFILEV1-P0470;PROFILEV1-P0471;PROFILEV1-P0472;PROFILEV1-P0473;PROFILEV1-P0474;PROFILEV1-P0475;PROFILEV1-P0476;PROFILEV1-P0477;PROFILEV1-P0478;PROFILEV1-P0479;PROFILEV1-P0480;PROFILEV1-P0481;PROFILEV1-P0482;PROFILEV1-P0483;PROFILEV1-P0484;PROFILEV1-P0485;PROFILEV1-P0486;PROFILEOLD-P0017;PROFILEOLD-P0026;PROFILEOLD-P0027;PROFILEOLD-P0028;PROFILEOLD-P0045;PROFILEOLD-P0117;PROFILEOLD-P0143;PROFILEOLD-P0150;PROFILEOLD-P0205;PROFILEOLD-P0206;PROFILEOLD-P0210;PROFILEOLD-P0211;PROFILEOLD-P0216;PROFILEOLD-P0259;PROFILEOLD-P0260;PROFILEOLD-P0288;PROFILEOLD-P0291;PROFILEOLD-P0293;PROFILEOLD-P0354;PROFILEOLD-P0435;PROFILEOLD-P0436;PROFILEOLD-P0437;PROFILEOLD-P0438;PROFILEOLD-P0439;PROFILEOLD-P0440;PROFILEOLD-P0441;PROFILEOLD-P0442;PROFILEOLD-P0443;PROFILEOLD-P0444;PROFILEOLD-P0445;PROFILEOLD-P0446;PROFILEOLD-P0447;PROFILEOLD-P0448;PROFILEOLD-P0449;PROFILEOLD-P0450;PROFILEOLD-P0451;PROFILEOLD-P0452;PROFILEOLD-P0453;PROFILEOLD-P0454,78,"[{""id"":""PROFILEV1-P0046"",""pedido"":""Não pode criar, editar, aprovar ou publicar oportunidades."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 46 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0055"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 55 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0056"",""pedido"":""Publicação institucional"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 56 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0057"",""pedido"":""Publicar, suspender, arquivar e programar a visibilidade de oportunidades previamente validadas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 57 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0076"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 76 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0148"",""pedido"":""Publicar oportunidade"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 148 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0174"",""pedido"":""Âmbito de publicação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 174 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0181"",""pedido"":""Publicação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 181 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0236"",""pedido"":""Publicar oportunidade aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 236 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0237"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 237 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0241"",""pedido"":""Publicar oportunidade ainda Em validação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 241 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0242"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 242 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0247"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 247 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0290"",""pedido"":""Falha na submissão ou publicação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 290 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0291"",""pedido"":""Preservar dados, impedir duplicação, repetir de forma controlada e reverter publicação parcial."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 291 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0319"",""pedido"":""Suspender o fluxo ou a publicação e restringir alterações."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 319 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0322"",""pedido"":""Erro material ou denúncia após publicação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 322 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0324"",""pedido"":""Publicador responsável, coordenação e conformidade conforme severidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 324 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0386"",""pedido"":""O sistema bloqueia a publicação de oportunidade não validada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 386 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0467"",""pedido"":""TC-PB-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 467 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0468"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 468 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0469"",""pedido"":""Oportunidade Aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 469 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0470"",""pedido"":""Programar e executar publicação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 470 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0471"",""pedido"":""Estado Publicada na data definida; evento auditado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 471 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0472"",""pedido"":""TC-PB-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 472 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0473"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 473 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0474"",""pedido"":""Oportunidade Em validação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 474 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0475"",""pedido"":""Tentar publicar."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 475 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0476"",""pedido"":""Operação bloqueada por estado inválido."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 476 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0477"",""pedido"":""TC-PB-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 477 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0478"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 478 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0479"",""pedido"":""Oportunidade aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 479 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0480"",""pedido"":""Tentar alterar conteúdo técnico."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 480 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0481"",""pedido"":""Edição bloqueada; opção de devolução ao fluxo apresentada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 481 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0482"",""pedido"":""TC-PB-04"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 482 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0483"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 483 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0484"",""pedido"":""Oportunidade Publicada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 484 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0485"",""pedido"":""Suspender sem motivo e depois com motivo."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 485 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0486"",""pedido"":""Primeira tentativa bloqueada; segunda aceite e notificada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 486 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0017"",""pedido"":""Não pode criar, editar, aprovar ou publicar oportunidades."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 17 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0026"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 26 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0027"",""pedido"":""Publicação institucional"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 27 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0028"",""pedido"":""Publicar, suspender, arquivar e programar a visibilidade de oportunidades previamente validadas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 28 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0045"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 45 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0117"",""pedido"":""Publicar oportunidade"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 117 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0143"",""pedido"":""Âmbito de publicação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 143 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0150"",""pedido"":""Publicação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 150 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0205"",""pedido"":""Publicar oportunidade aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 205 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0206"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 206 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0210"",""pedido"":""Publicar oportunidade ainda Em validação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 210 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0211"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 211 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0216"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 216 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0259"",""pedido"":""Falha na submissão ou publicação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 259 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0260"",""pedido"":""Preservar dados, impedir duplicação, repetir de forma controlada e reverter publicação parcial."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 260 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0288"",""pedido"":""Suspender o fluxo ou a publicação e restringir alterações."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 288 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0291"",""pedido"":""Erro material ou denúncia após publicação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 291 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0293"",""pedido"":""Publicador responsável, coordenação e conformidade conforme severidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 293 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0354"",""pedido"":""O sistema bloqueia a publicação de oportunidade não validada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 354 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0435"",""pedido"":""TC-PB-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 435 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0436"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 436 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0437"",""pedido"":""Oportunidade Aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 437 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0438"",""pedido"":""Programar e executar publicação."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 438 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0439"",""pedido"":""Estado Publicada na data definida; evento auditado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 439 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0440"",""pedido"":""TC-PB-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 440 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0441"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 441 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0442"",""pedido"":""Oportunidade Em validação"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 442 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0443"",""pedido"":""Tentar publicar."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 443 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0444"",""pedido"":""Operação bloqueada por estado inválido."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 444 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0445"",""pedido"":""TC-PB-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 445 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0446"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 446 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0447"",""pedido"":""Oportunidade aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 447 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0448"",""pedido"":""Tentar alterar conteúdo técnico."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 448 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0449"",""pedido"":""Edição bloqueada; opção de devolução ao fluxo apresentada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 449 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0450"",""pedido"":""TC-PB-04"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 450 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0451"",""pedido"":""Publicador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 451 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0452"",""pedido"":""Oportunidade Publicada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 452 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0453"",""pedido"":""Suspender sem motivo e depois com motivo."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 453 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0454"",""pedido"":""Primeira tentativa bloqueada; segunda aceite e notificada."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 454 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes.","25 publica draft409; fixture confirma estado incompatível; todos os atos positivos de publicação integral continuam pendentes. | [Workflow QA 10/10/2026] Publicador25:pub interna18; pública19 com2derivadas ClamD; confirmfalse422/hashdiverso409; alteração privada não vazou; suspensãoGETpúblico404. Fundiário20externapendente422. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-13,Auditor: consulta filtrada/exportação e ausência de escrita,"Gestao de perfis investeMOZ v1.docx | parágrafo 41 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 59 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 77 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 100 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 169 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 176 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 193 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 251 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 252 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 254 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 257 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 369 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 377 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 487 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 488 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 489 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 490 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 491 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 492 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 493 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 494 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 495 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 496 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 497 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 498 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 499 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 500 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 501 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 12 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 30 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 46 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 69 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 138 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 145 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 162 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 220 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 221 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 223 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 226 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 337 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 345 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 455 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 456 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 457 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 458 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 459 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 460 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 461 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 462 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 463 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 464 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 465 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 466 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 467 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 468 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 469 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"/perfis/auditoria usa audit_events existentes, filtros e JSON minimizado; Auditor conserva impedimento de escrita.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,26 recupera substituição filtrada e exporta metadados sem snapshots privados;20 recebe403;31 multirrole edição403. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,"Interface, exportação ampliada autorizada por classificação e consulta dos restantes domínios administrativos.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0041;PROFILEV1-P0059;PROFILEV1-P0077;PROFILEV1-P0100;PROFILEV1-P0169;PROFILEV1-P0176;PROFILEV1-P0193;PROFILEV1-P0251;PROFILEV1-P0252;PROFILEV1-P0254;PROFILEV1-P0257;PROFILEV1-P0369;PROFILEV1-P0377;PROFILEV1-P0487;PROFILEV1-P0488;PROFILEV1-P0489;PROFILEV1-P0490;PROFILEV1-P0491;PROFILEV1-P0492;PROFILEV1-P0493;PROFILEV1-P0494;PROFILEV1-P0495;PROFILEV1-P0496;PROFILEV1-P0497;PROFILEV1-P0498;PROFILEV1-P0499;PROFILEV1-P0500;PROFILEV1-P0501;PROFILEOLD-P0012;PROFILEOLD-P0030;PROFILEOLD-P0046;PROFILEOLD-P0069;PROFILEOLD-P0138;PROFILEOLD-P0145;PROFILEOLD-P0162;PROFILEOLD-P0220;PROFILEOLD-P0221;PROFILEOLD-P0223;PROFILEOLD-P0226;PROFILEOLD-P0337;PROFILEOLD-P0345;PROFILEOLD-P0455;PROFILEOLD-P0456;PROFILEOLD-P0457;PROFILEOLD-P0458;PROFILEOLD-P0459;PROFILEOLD-P0460;PROFILEOLD-P0461;PROFILEOLD-P0462;PROFILEOLD-P0463;PROFILEOLD-P0464;PROFILEOLD-P0465;PROFILEOLD-P0466;PROFILEOLD-P0467;PROFILEOLD-P0468;PROFILEOLD-P0469,56,"[{""id"":""PROFILEV1-P0041"",""pedido"":""Gerir utilizadores, perfis, permissões, taxonomias, conteúdos, fluxos, auditoria e configurações."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 41 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0059"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 59 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0077"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 77 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0100"",""pedido"":""Total, com auditoria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 100 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0169"",""pedido"":""Consultar histórico e registos de auditoria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 169 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0176"",""pedido"":""Exportar relatórios"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 176 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0193"",""pedido"":""Diagrama 2 — Casos de uso essenciais e transições entre Promotor, Validador, Publicador e Utilizador público; os casos administrativos e de auditoria permanecem segregados."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 193 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0251"",""pedido"":""Consultar e exportar trilho de auditoria"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 251 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0252"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 252 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0254"",""pedido"":""Somente leitura e proteção de dados na exportação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 254 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0257"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 257 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0369"",""pedido"":""Criação, validação, publicação e auditoria são incompatíveis em operações críticas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 369 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0377"",""pedido"":""Auditoria e revisão periódica"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 377 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0487"",""pedido"":""TC-AU-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 487 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0488"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 488 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0489"",""pedido"":""Registos de auditoria existentes"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 489 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0490"",""pedido"":""Filtrar por utilizador, ação, recurso e período."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 490 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0491"",""pedido"":""Resultados completos e somente de leitura."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 491 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0492"",""pedido"":""TC-AU-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 492 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0493"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 493 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0494"",""pedido"":""Relatório disponível"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 494 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0495"",""pedido"":""Exportar relatório de conformidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 495 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0496"",""pedido"":""Exportação produzida com proteção ou minimização de dados pessoais."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 496 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0497"",""pedido"":""TC-AU-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 497 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0498"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 498 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0499"",""pedido"":""Sessão ativa"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 499 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0500"",""pedido"":""Tentar alterar perfil, oportunidade ou configuração."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 500 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0501"",""pedido"":""Todas as operações de escrita negadas e registadas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 501 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0012"",""pedido"":""Gerir utilizadores, perfis, permissões, taxonomias, conteúdos, fluxos, auditoria e configurações."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 12 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0030"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 30 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0046"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 46 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0069"",""pedido"":""Total, com auditoria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 69 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0138"",""pedido"":""Consultar histórico e registos de auditoria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 138 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0145"",""pedido"":""Exportar relatórios"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 145 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0162"",""pedido"":""Diagrama 2 — Casos de uso essenciais e transições entre Promotor, Validador, Publicador e Utilizador público; os casos administrativos e de auditoria permanecem segregados."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 162 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0220"",""pedido"":""Consultar e exportar trilho de auditoria"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 220 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0221"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 221 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0223"",""pedido"":""Somente leitura e proteção de dados na exportação."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 223 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0226"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 226 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0337"",""pedido"":""Criação, validação, publicação e auditoria são incompatíveis em operações críticas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 337 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0345"",""pedido"":""Auditoria e revisão periódica"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 345 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0455"",""pedido"":""TC-AU-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 455 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0456"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 456 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0457"",""pedido"":""Registos de auditoria existentes"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 457 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0458"",""pedido"":""Filtrar por utilizador, ação, recurso e período."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 458 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0459"",""pedido"":""Resultados completos e somente de leitura."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 459 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0460"",""pedido"":""TC-AU-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 460 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0461"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 461 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0462"",""pedido"":""Relatório disponível"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 462 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0463"",""pedido"":""Exportar relatório de conformidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 463 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0464"",""pedido"":""Exportação produzida com proteção ou minimização de dados pessoais."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 464 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0465"",""pedido"":""TC-AU-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 465 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0466"",""pedido"":""Auditor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 466 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0467"",""pedido"":""Sessão ativa"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 467 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0468"",""pedido"":""Tentar alterar perfil, oportunidade ou configuração."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 468 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0469"",""pedido"":""Todas as operações de escrita negadas e registadas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 469 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",26 recupera substituição filtrada e exporta metadados sem snapshots privados;20 recebe403;31 multirrole edição403.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-14,Superutilizador: administração controlada e elevação temporária,"Gestao de perfis investeMOZ v1.docx | parágrafo 107 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 114 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 121 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 128 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 135 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 142 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 149 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 156 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 345 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 373 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 390 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 397 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 398 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 399 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 400 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 401 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 402 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 403 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 404 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 405 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 406 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 76 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 83 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 90 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 97 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 104 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 111 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 118 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 125 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 313 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 341 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 358 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 365 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 367 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 368 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 369 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 370 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 372 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 373 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 374 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"PortalSuperusers/Administration; MFA recente, motivo, aprovação independente e validade15min; aprovador deve continuar na dupla.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"27 administra pedidos/papéis, autoaprovação403, criação sem papel403; elevação API preparada, ainda sem ato operacional positivo completo. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"Demonstração da elevação completa, expiração, scope/action exatos e interface de administração.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0107;PROFILEV1-P0114;PROFILEV1-P0121;PROFILEV1-P0128;PROFILEV1-P0135;PROFILEV1-P0142;PROFILEV1-P0149;PROFILEV1-P0156;PROFILEV1-P0345;PROFILEV1-P0373;PROFILEV1-P0390;PROFILEV1-P0397;PROFILEV1-P0398;PROFILEV1-P0399;PROFILEV1-P0400;PROFILEV1-P0401;PROFILEV1-P0402;PROFILEV1-P0403;PROFILEV1-P0404;PROFILEV1-P0405;PROFILEV1-P0406;PROFILEOLD-P0076;PROFILEOLD-P0083;PROFILEOLD-P0090;PROFILEOLD-P0097;PROFILEOLD-P0104;PROFILEOLD-P0111;PROFILEOLD-P0118;PROFILEOLD-P0125;PROFILEOLD-P0313;PROFILEOLD-P0341;PROFILEOLD-P0358;PROFILEOLD-P0365;PROFILEOLD-P0367;PROFILEOLD-P0368;PROFILEOLD-P0369;PROFILEOLD-P0370;PROFILEOLD-P0372;PROFILEOLD-P0373;PROFILEOLD-P0374,40,"[{""id"":""PROFILEV1-P0107"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 107 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0114"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 114 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0121"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 121 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0128"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 128 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0135"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 135 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0142"",""pedido"":""Apenas com elevação temporária e validação independente"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 142 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0149"",""pedido"":""Apenas com elevação temporária e aprovação prévia"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 149 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0156"",""pedido"":""Apenas com elevação temporária e motivo obrigatório"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 156 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0345"",""pedido"":""A elevação temporária de privilégios para ações operacionais por um Superutilizador exige justificação, prazo de validade, aprovação independente e auditoria reforçada; não substitui os perfis de Promotor, Validador ou Publicador."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 345 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0373"",""pedido"":""Alinhado; mitiga elevação horizontal de privilégios."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 373 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0390"",""pedido"":""Testes automatizados cobrem acessos autorizados e negados, conflitos de papéis, elevação temporária, tentativas de acesso direto por identificador, exceções, escalamento, recurso e falhas técnicas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 390 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0397"",""pedido"":""TC-SU-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 397 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0398"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 398 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0399"",""pedido"":""MFA válido; dois titulares ativos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 399 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0400"",""pedido"":""Atribuir papel de Validador com validade definida."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 400 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0401"",""pedido"":""Papel atribuído; aprovador, período e valores registados na auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 401 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0402"",""pedido"":""TC-SU-02"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 402 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0403"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 403 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0404"",""pedido"":""Existem apenas dois titulares"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 404 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0405"",""pedido"":""Tentar desativar um deles sem substituição."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 405 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0406"",""pedido"":""Operação bloqueada; mensagem sobre mínimo obrigatório; evento auditado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 406 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0076"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 76 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0083"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 83 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0090"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 90 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0097"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 97 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0104"",""pedido"":""Apenas com elevação temporária aprovada"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 104 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0111"",""pedido"":""Apenas com elevação temporária e validação independente"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 111 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0118"",""pedido"":""Apenas com elevação temporária e aprovação prévia"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 118 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0125"",""pedido"":""Apenas com elevação temporária e motivo obrigatório"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 125 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0313"",""pedido"":""A elevação temporária de privilégios para ações operacionais por um Superutilizador exige justificação, prazo de validade, aprovação independente e auditoria reforçada; não substitui os perfis de Promotor, Validador ou Publicador."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 313 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0341"",""pedido"":""Alinhado; mitiga elevação horizontal de privilégios."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 341 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0358"",""pedido"":""Testes automatizados cobrem acessos autorizados e negados, conflitos de papéis, elevação temporária, tentativas de acesso direto por identificador, exceções, escalamento, recurso e falhas técnicas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 358 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0365"",""pedido"":""TC-SU-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 365 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0367"",""pedido"":""MFA válido; dois titulares ativos"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 367 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0368"",""pedido"":""Atribuir papel de Validador com validade definida."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 368 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0369"",""pedido"":""Papel atribuído; aprovador, período e valores registados na auditoria."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 369 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0370"",""pedido"":""TC-SU-02"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 370 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0372"",""pedido"":""Existem apenas dois titulares"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 372 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0373"",""pedido"":""Tentar desativar um deles sem substituição."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 373 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0374"",""pedido"":""Operação bloqueada; mensagem sobre mínimo obrigatório; evento auditado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 374 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","27 administra pedidos/papéis, autoaprovação403, criação sem papel403; elevação API preparada, ainda sem ato operacional positivo completo.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-15,Exatamente dois Superutilizadores: inicialização e substituição atómica,"Gestao de perfis investeMOZ v1.docx | parágrafo 42 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 265 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 266 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 267 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 268 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 269 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 387 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 508 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 509 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 510 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 511 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 512 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 513 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 514 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 515 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 516 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 517 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 10 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 13 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 41 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 231 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 234 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 235 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 236 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 238 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 355 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 366 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 371 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 376 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Dupla singleton ligada a users, CHECK distintos, triggerDELETE/TRUNCATE, versão/lock, aprovação e atualização única.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"Inicialização27/28 pelo29; terceira atribuição422; substituição28→30 com aprovação28 independente de27, dupla27/30; replay409, sessão28invalidada. TriggerDELETE testado. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"Interface, testes concorrentes em sessões simultâneas e cerimónia ativa com titulares reais ainda não designados.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.","Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0042;PROFILEV1-P0265;PROFILEV1-P0266;PROFILEV1-P0267;PROFILEV1-P0268;PROFILEV1-P0269;PROFILEV1-P0387;PROFILEV1-P0508;PROFILEV1-P0509;PROFILEV1-P0510;PROFILEV1-P0511;PROFILEV1-P0512;PROFILEV1-P0513;PROFILEV1-P0514;PROFILEV1-P0515;PROFILEV1-P0516;PROFILEV1-P0517;PROFILEOLD-P0010;PROFILEOLD-P0013;PROFILEOLD-P0041;PROFILEOLD-P0231;PROFILEOLD-P0234;PROFILEOLD-P0235;PROFILEOLD-P0236;PROFILEOLD-P0238;PROFILEOLD-P0355;PROFILEOLD-P0366;PROFILEOLD-P0371;PROFILEOLD-P0376,29,"[{""id"":""PROFILEV1-P0042"",""pedido"":""Devem existir exatamente dois titulares ativos do perfil Superutilizador. A substituição de um titular deve ser concluída numa única operação controlada, sem permitir que o número de titulares ativos fique temporariamente abaixo ou acima de dois; a autenticação multifator é obrigatória e todas as ações críticas exigem confirmação reforçada e registo de auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 42 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0265"",""pedido"":""AC-14"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 265 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0266"",""pedido"":""Alterar o conjunto de superutilizadores ativos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 266 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0267"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 267 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0268"",""pedido"":""Negar, salvo substituição controlada"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 268 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0269"",""pedido"":""Negar qualquer criação de terceiro titular ou desativação de um dos dois titulares sem substituição simultânea; permitir apenas substituição atómica com MFA, aprovação independente, invalidação imediata das sessões do titular substituído, alerta e auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 269 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0387"",""pedido"":""Devem existir exatamente dois superutilizadores ativos. O sistema deve bloquear a criação de um terceiro titular e a desativação de um dos dois titulares sem substituição simultânea. A substituição deve ser executada como uma única operação controlada, exigir autenticação multifator e aprovação independente, invalidar imediatamente as sessões do titular substituído e gerar alerta e registo de auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 387 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0508"",""pedido"":""TC-SU-04"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 508 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0509"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 509 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0510"",""pedido"":""Existem dois superutilizadores activos"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 510 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0511"",""pedido"":""Tentar criar um terceiro titular."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 511 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0512"",""pedido"":""Operação bloqueada, alerta emitido e tentativa registada na auditoria."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 512 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0513"",""pedido"":""TC-SU-05"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 513 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0514"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 514 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0515"",""pedido"":""Existem dois superutilizadores ativos e um substituto aprovado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 515 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0516"",""pedido"":""Substituir um titular numa única operação com MFA e aprovação independente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 516 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0517"",""pedido"":""O conjunto mantém exatamente dois titulares durante toda a transacção, as sessões do titular substituído são invalidadas imediatamente e a substituição fica integralmente auditada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 517 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0010"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 10 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0013"",""pedido"":""Devem existir exatamente dois titulares ativos; autenticação multifator obrigatória; ações críticas com confirmação reforçada e registo de auditoria."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 13 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0041"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 41 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0231"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 231 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0234"",""pedido"":""AC-14"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 234 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0235"",""pedido"":""Reduzir superutilizadores ativos para menos de dois"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 235 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0236"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 236 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0238"",""pedido"":""Regra de exatamente dois titulares ativos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 238 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0355"",""pedido"":""Existem exatamente dois superutilizadores ativos e qualquer alteração nesse grupo gera alerta e auditoria."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 355 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0366"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 366 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0371"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 371 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0376"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 376 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","Inicialização27/28 pelo29; terceira atribuição422; substituição28→30 com aprovação28 independente de27, dupla27/30; replay409, sessão28invalidada. TriggerDELETE testado.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-16,Recuperar acesso preservando MFA e dupla,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Códigos de recuperação Fortify e substituição independente; bloqueio de desativaçãoMFA, mudançaemail/eliminação de titular.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,30 recupera sessãoMFA noutra sessão pelo códigoFortify; reutilização422 sem autenticação; DELETE-MFA/conta e PATCHemail403. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,Procedimento institucional quando ambos perdem todos os meios; aceitação visual e guarda local dos códigos sem os transmitir.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Recuperação normal mantém MFA e dois titulares; código consumido não autentica; emergência não é desativaçãoMFA ou key:generate.,P0,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-16-USER-20261010,1,"[{""id"":""AUD-PROFILE-16-USER-20261010"",""pedido"":""Recuperar acesso preservando MFA e dupla"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Recuperação normal mantém MFA e dois titulares; código consumido não autentica; emergência não é desativaçãoMFA ou key:generate."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",30 recupera sessãoMFA noutra sessão pelo códigoFortify; reutilização422 sem autenticação; DELETE-MFA/conta e PATCHemail403.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-17,Revogação imediata com histórico e invalidação de sessões/tokens,"Gestao de perfis investeMOZ v1.docx | parágrafo 6 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 66 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 99 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 192 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 261 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 264 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 276 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 378 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 389 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 407 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 408 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 409 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 410 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 411 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 37 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 68 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 161 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 230 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 233 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 245 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 346 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 357 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 375 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 377 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 378 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 379 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Atribuição retida, revision de autorização por conta, remember_token revogado; adaptação sessions/personal_access_tokens quando presentes.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,24 antigo cookie401; nova sessãoMFA autentica mas acesso de papel403;28 substituído igual. Histórico original preservado. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,"Tokens pessoais não instalados/ensaiados no alvo, dispositivos/integradores e interface por consumidor.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.","Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões.",P0,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0006;PROFILEV1-P0066;PROFILEV1-P0099;PROFILEV1-P0192;PROFILEV1-P0261;PROFILEV1-P0264;PROFILEV1-P0276;PROFILEV1-P0378;PROFILEV1-P0389;PROFILEV1-P0407;PROFILEV1-P0408;PROFILEV1-P0409;PROFILEV1-P0410;PROFILEV1-P0411;PROFILEOLD-P0037;PROFILEOLD-P0068;PROFILEOLD-P0161;PROFILEOLD-P0230;PROFILEOLD-P0233;PROFILEOLD-P0245;PROFILEOLD-P0346;PROFILEOLD-P0357;PROFILEOLD-P0375;PROFILEOLD-P0377;PROFILEOLD-P0378;PROFILEOLD-P0379,26,"[{""id"":""PROFILEV1-P0006"",""pedido"":""Esta versão consolidada define o modelo de governação de identidades e acessos do Portal InvesteMoz. A solução combina RBAC e ABAC, estabelece seis perfis, restringe ações operacionais por propriedade, organização, tipo de oportunidade e estado do processo e aplica segregação de funções, autenticação multifator, auditoria integral e revogação imediata. O documento reúne a matriz de permissões, os fluxos normais e excecionais, o modelo de dados, a solução tecnológica, os critérios de aceitação e os casos de teste necessários para implementação e validação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 6 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0066"",""pedido"":""flowchart LRU[Utilizador autenticado] --> P{Perfil activo}P --> SU[Superutilizador]P --> UP[Utilizador público]P --> PR[Promotor]P --> VA[Validador]P --> PB[Publicador]P --> AU[Auditor]SU --> A1[Administrar utilizadores, perfis, permissões e configurações]SU --> ET{Ação operacional?}ET -->|Sim| ET1[Exigir elevação temporária, aprovação independente e prazo]ET1 --> A7[Executar apenas a acção aprovada e auditar]UP --> A2[Consultar oportunidades e gerir dados próprios]PR --> A3[Criar, editar e submeter oportunidades da organização]VA --> A4[Rever, solicitar correções, aprovar ou rejeitar]PB --> A5[Publicar, suspender e arquivar oportunidades validadas]AU --> A6[Consultar registos, configurações e relatórios]A1 --> C[Controlos transversais]A2 --> CA3 --> CA4 --> CA5 --> CA6 --> CA7 --> CC --> C1[RBAC + ABAC]C --> C2[Menor privilégio]C --> C3[Segregação de funções]C --> C4[Negar por defeito]C --> C5[Auditoria integral]C --> C6[Revogação imediata]"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 66 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0099"",""pedido"":""Atribuir ou revogar papéis"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 99 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0192"",""pedido"":""flowchart TBSU[Superutilizador] --> SU1[Gerir utilizadores e perfis]SU --> SU2[Configurar permissões e fluxos]SU --> SU3[Revogar acessos e consultar auditoria]UP[Utilizador público] --> UP1[Registar e autenticar-se]UP --> UP2[Pesquisar e guardar oportunidades]UP --> UP3[Gerir dados, alertas e pedidos próprios]PR[Promotor] --> PR1[Solicitar autorização por tipo]PR --> PR2[Criar e guardar rascunho]PR --> PR3[Anexar documentos e submeter]PR --> PR4[Responder a correções e acompanhar estado]VA[Validador] --> VA1[Receber processo submetido]VA --> VA2[Verificar dados e documentos]VA --> VA3[Solicitar correção, aprovar ou rejeitar]PB[Publicador] --> PB1[Confirmar aprovação técnica]PB --> PB2[Publicar ou programar publicação]PB --> PB3[Suspender ou arquivar com motivo]AU[Auditor] --> AU1[Consultar trilho de auditoria]AU --> AU2[Analisar conflitos e acessos]AU --> AU3[Exportar relatório de conformidade]PR3 --> VA1VA3 -->|Aprovada| PB1VA3 -->|Correção solicitada| PR4PB2 --> UP2"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 192 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0261"",""pedido"":""Revogar papel privilegiado"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 261 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0264"",""pedido"":""Confirmação reforçada, motivo e revogação imediata."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 264 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0276"",""pedido"":""Usar sessão após revogação do perfil"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 276 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0378"",""pedido"":""Trilhos imutáveis, expiração, recertificação e revogação de acessos."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 378 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0389"",""pedido"":""A revogação de perfil produz efeito imediato em sessões e tokens ativos."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 389 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0407"",""pedido"":""TC-SU-03"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 407 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0408"",""pedido"":""Superutilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 408 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0409"",""pedido"":""Utilizador privilegiado ativo"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 409 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0410"",""pedido"":""Revogar o papel e reutilizar token anterior."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 410 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0411"",""pedido"":""Revogação imediata; token rejeitado; sessões encerradas."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 411 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0037"",""pedido"":""flowchart LRU[Utilizador autenticado] --> P{Perfil ativo}P --> SU[Superutilizador]P --> UP[Utilizador público]P --> PR[Promotor]P --> VA[Validador]P --> PB[Publicador]P --> AU[Auditor]SU --> A1[Administrar utilizadores, perfis, permissões e configurações]UP --> A2[Consultar oportunidades e gerir dados próprios]PR --> A3[Criar, editar e submeter oportunidades da organização]VA --> A4[Rever, solicitar correções, aprovar ou rejeitar]PB --> A5[Publicar, suspender e arquivar oportunidades validadas]AU --> A6[Consultar logs, configurações e relatórios]A1 --> C[Controlos transversais]A2 --> CA3 --> CA4 --> CA5 --> CA6 --> CC --> C1[RBAC + ABAC]C --> C2[Menor privilégio]C --> C3[Segregação de funções]C --> C4[Negar por defeito]C --> C5[Auditoria integral]C --> C6[Revogação imediata]"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 37 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0068"",""pedido"":""Atribuir ou revogar papéis"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 68 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0161"",""pedido"":""flowchart TBSU[Superutilizador] --> SU1[Gerir utilizadores e perfis]SU --> SU2[Configurar permissões e fluxos]SU --> SU3[Revogar acessos e consultar auditoria]UP[Utilizador público] --> UP1[Registar e autenticar-se]UP --> UP2[Pesquisar e guardar oportunidades]UP --> UP3[Gerir dados, alertas e pedidos próprios]PR[Promotor] --> PR1[Solicitar autorização por tipo]PR --> PR2[Criar e guardar rascunho]PR --> PR3[Anexar documentos e submeter]PR --> PR4[Responder a correções e acompanhar estado]VA[Validador] --> VA1[Receber processo submetido]VA --> VA2[Verificar dados e documentos]VA --> VA3[Solicitar correção, aprovar ou rejeitar]PB[Publicador] --> PB1[Confirmar aprovação técnica]PB --> PB2[Publicar ou programar publicação]PB --> PB3[Suspender ou arquivar com motivo]AU[Auditor] --> AU1[Consultar trilho de auditoria]AU --> AU2[Analisar conflitos e acessos]AU --> AU3[Exportar relatório de conformidade]PR3 --> VA1VA3 -->|Aprovada| PB1VA3 -->|Correção solicitada| PR4PB2 --> UP2"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 161 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0230"",""pedido"":""Revogar papel privilegiado"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 230 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0233"",""pedido"":""Confirmação reforçada, motivo e revogação imediata."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 233 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0245"",""pedido"":""Usar sessão após revogação do perfil"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 245 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0346"",""pedido"":""Trilhos imutáveis, expiração, recertificação e revogação de acessos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 346 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0357"",""pedido"":""A revogação de perfil produz efeito imediato em sessões e tokens ativos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 357 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0375"",""pedido"":""TC-SU-03"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 375 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0377"",""pedido"":""Utilizador privilegiado ativo"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 377 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0378"",""pedido"":""Revogar o papel e reutilizar token anterior."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 378 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0379"",""pedido"":""Revogação imediata; token rejeitado; sessões encerradas."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 379 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",24 antigo cookie401; nova sessãoMFA autentica mas acesso de papel403;28 substituído igual. Histórico original preservado.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-18,"Validade, reavaliação por inatividade e documentação expirada","Gestao de perfis investeMOZ v1.docx | parágrafo 296 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 310 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 312 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 336 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 252 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 265 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 279 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 281 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 305 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,starts_at/expires_at/revoked_at consultados a cada pedido; atribuições documentadas sem cache de autorização.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Fixture de papel expirado não autoriza; MFA antigo não permite decisão. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,"Revalidação/inatividade/expiração documental, parâmetros aprovados e avisos; não inventar prazos.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0296;PROFILEV1-P0310;PROFILEV1-P0312;PROFILEV1-P0336;PROFILEOLD-P0252;PROFILEOLD-P0265;PROFILEOLD-P0279;PROFILEOLD-P0281;PROFILEOLD-P0305,9,"[{""id"":""PROFILEV1-P0296"",""pedido"":""Coordenador de validação quando não houver substituto ou o SLA expirar."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 296 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0310"",""pedido"":""Inatividade do Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 310 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0312"",""pedido"":""Arquivar por inatividade; reabertura apenas por utilizador autorizado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 312 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0336"",""pedido"":""Revisão e revogação: acessos privilegiados são revistos periodicamente; contas inativas, vínculos expirados ou documentos vencidos geram suspensão automática ou tarefa de revalidação."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 336 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0252"",""pedido"":""flowchart TDA[Promotor cria rascunho] --> B{Dados e documentos completos?}B -->|Não| B1[Guardar rascunho e indicar pendências]B1 --> AB -->|Sim| C[Submeter oportunidade]C --> C1{Serviço disponível e anexos íntegros?}C1 -->|Não| C2[Manter dados, registar incidente e tentar novamente]C2 --> C3{Prazo técnico excedido?}C3 -->|Não| C1C3 -->|Sim| ES1[Escalar para suporte e gestor operacional]ES1 --> C1C1 -->|Sim| D[Estado: Submetida]D --> E[Distribuição automática ao Validador]E --> F{Validador disponível e sem conflito?}F -->|Conflito| F1[Registar impedimento e reatribuir]F1 --> EF -->|Indisponível| F2{SLA de atribuição excedido?}F2 -->|Não| EF2 -->|Sim| ES2[Escalar ao coordenador de validação]ES2 --> EF -->|Sim| H[Validação técnica e documental]H --> H1{Dependência externa ou dúvida crítica?}H1 -->|Sim| H2[Estado: Pendente de parecer]H2 --> H3{Parecer recebido no prazo?}H3 -->|Sim| HH3 -->|Não| ES3[Escalar ao responsável técnico ou jurídico]ES3 --> HH1 -->|Não| I{Decisão}I -->|Corrigir| J[Registar motivo, campos e prazo]J --> K[Estado: Correção solicitada]K --> K1{Promotor responde no prazo?}K1 -->|Sim| L[Corrigir e voltar a submeter]L --> DK1 -->|Não| K2[Enviar lembrete e conceder tolerância]K2 --> K3{Tolerância excedida?}K3 -->|Não| K1K3 -->|Sim| K4[Arquivar por inatividade, com reabertura autorizada]I -->|Corrigir novamente| J2{Limite de ciclos excedido?}J2 -->|Não| JJ2 -->|Sim| ES4[Escalar ao coordenador para decisão assistida]ES4 --> II -->|Rejeitar| M[Registar fundamento e evidências]M --> N[Estado: Rejeitada]N --> N1{Promotor apresenta recurso no prazo?}N1 -->|Não| N2[Encerrar processo]N1 -->|Sim| N3[Encaminhar a instância distinta de recurso]N3 --> N4{Decisão de recurso}N4 -->|Manter rejeição| N2N4 -->|Reabrir| DI -->|Aprovar| P[Estado: Aprovada]P --> Q[Publicador verifica aprovação, integridade e conformidade]Q --> R{Condições de publicação satisfeitas?}R -->|Não corrigível| S[Devolver para correção administrativa]S --> JR -->|Risco grave ou ilegalidade| ES5[Suspender fluxo e escalar à gestão e conformidade]ES5 --> ES6{Decisão extraordinária}ES6 -->|Regularizar| SES6 -->|Cancelar| N2R -->|Sim| T[Publicar ou programar publicação]T --> T1{Publicação concluída?}T1 -->|Falha técnica| T2[Reverter, preservar versão e abrir incidente]T2 --> ES1T1 -->|Sim| U[Estado: Publicada]U --> V{Denúncia, erro material ou risco superveniente?}V -->|Não| UV -->|Sim| W[Suspensão preventiva com motivo e prazo]W --> X[Notificar responsáveis e iniciar revisão urgente]X --> Y{Resultado da revisão}Y -->|Repor| UY -->|Corrigir| SY -->|Arquivar| Z[Estado: Arquivada]"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 252 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0265"",""pedido"":""Coordenador de validação quando não houver substituto ou o SLA expirar."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 265 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0279"",""pedido"":""Inatividade do Promotor"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 279 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0281"",""pedido"":""Arquivar por inatividade; reabertura apenas por utilizador autorizado."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 281 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0305"",""pedido"":""Revisão e revogação: acessos privilegiados são revistos periodicamente; contas inativas, vínculos expirados ou documentos vencidos geram suspensão automática ou tarefa de revalidação."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 305 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",Fixture de papel expirado não autoriza; MFA antigo não permite decisão.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-19,Coordenadores de validação/publicação e pareceres técnico-jurídicos,"Gestao de perfis investeMOZ v1.docx | parágrafo 300 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 302 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 308 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 328 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 269 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 271 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 277 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 297 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Responsabilidades mapeadas e compatibilidade por papel validadas; entidades existentes de tarefa/auditoria a reutilizar. | [Workflow QA 10/10/2026] Tarefas CRM existentes com source_system/external_id/correlation_id ligados ao ID da oportunidade; fila sem responsável/prazo inventado, atribuição explícita pelo coordenador validada. Gates requerem responsabilidade técnica/jurídica. | [Semântica QA 10/10/2026] Filas por estado/recurso/assignee e nomes de participantes elegíveis no servidor; tasks existentes recebem pareceres/atribuições/revisões/editoriais. SLAunconfigured/due_atnull, sem prazos nem titulares reais inventados.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Semântica QA 10/10/2026] Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos.","Responsabilidade validation_coordinator em Auditor422; papéis/responsabilidades armazenáveis, filas e reatribuições não implementadas. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Atribuição24 persistida, tarefas review/correction/publication criadas e concluídas conforme ações; due_at=null/SLAunconfigured. Papéis/responsabilidades reais reavaliados; não cria crm_opportunity paralela. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.",parcial,"Implementar filas/atribuição, conflito, disponibilidade, parecer e escalamento sem novos perfis ou identidades. | [Workflow QA 10/10/2026] Fila/editor próprios, reatribuição/disponibilidade, coordenação editorial, parecer externo e escalamento completos; testes visuais. Responsáveis/prazos reais ainda não definidos. | [Semântica QA 10/10/2026] Visual das filas e reatribuições; decisão exata:qual política versionada define prazos,tolerância,ciclos e escalamento? Quem detém as competências institucionais? Nenhum prazo/responsável real atribuído em QA.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0300;PROFILEV1-P0302;PROFILEV1-P0308;PROFILEV1-P0328;PROFILEOLD-P0269;PROFILEOLD-P0271;PROFILEOLD-P0277;PROFILEOLD-P0297,8,"[{""id"":""PROFILEV1-P0300"",""pedido"":""Coordenador designa responsável independente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 300 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0302"",""pedido"":""Parecer técnico ou jurídico pendente"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 302 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0308"",""pedido"":""Coordenador decide após o limite de ciclos, podendo convocar análise assistida."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 308 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0328"",""pedido"":""Nível 1: coordenador; Nível 2: gestor operacional; Nível 3: direção, conforme criticidade."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 328 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0269"",""pedido"":""Coordenador designa responsável independente."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 269 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0271"",""pedido"":""Parecer técnico ou jurídico pendente"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 271 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0277"",""pedido"":""Coordenador decide após o limite de ciclos, podendo convocar análise assistida."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 277 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0297"",""pedido"":""Nível 1: coordenador; Nível 2: gestor operacional; Nível 3: direção, conforme criticidade."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 297 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes.","Responsabilidade validation_coordinator em Auditor422; papéis/responsabilidades armazenáveis, filas e reatribuições não implementadas. | [Workflow QA 10/10/2026] Atribuição24 persistida, tarefas review/correction/publication criadas e concluídas conforme ações; due_at=null/SLAunconfigured. Papéis/responsabilidades reais reavaliados; não cria crm_opportunity paralela. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-20,"Suporte técnico, incidentes e preservação da submissão","Gestao de perfis investeMOZ v1.docx | parágrafo 32 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 283 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 292 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 293 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 309 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 261 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 262 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 278 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,Balcão/tarefas/audit_events existentes; suporte mapeado sem acesso documental automático; nenhum gestor fictício.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Correspondência documental preparada; protocolo de incidentes da submissão não implementado neste workflow. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,não implementado,"Incidentes recuperáveis, suporte atribuído, falha de submissão/ficheiro sem perda, alertas e estados próprios.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.","Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0032;PROFILEV1-P0283;PROFILEV1-P0292;PROFILEV1-P0293;PROFILEV1-P0309;PROFILEOLD-P0261;PROFILEOLD-P0262;PROFILEOLD-P0278,8,"[{""id"":""PROFILEV1-P0032"",""pedido"":""Siglas e conceitos: RBAC designa o controlo de acesso baseado em papéis; ABAC designa o controlo de acesso baseado em atributos; MFA designa a autenticação multifator; e SLA designa o nível de serviço aplicável a uma etapa ou incidente. Neste documento, papel corresponde ao conjunto de permissões atribuível a uma conta, enquanto perfil representa a função funcional exercida pelo utilizador no Portal InvesteMoz."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 32 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0283"",""pedido"":""flowchart TDA[Promotor cria rascunho] --> B{Dados e documentos completos?}B -->|Não| B1[Guardar rascunho e indicar pendências]B1 --> AB -->|Sim| C[Submeter oportunidade]C --> C1{Serviço disponível e anexos íntegros?}C1 -->|Não| C2[Manter dados, registar incidente e tentar novamente]C2 --> C3{Prazo técnico excedido?}C3 -->|Não| C1C3 -->|Sim| ES1[Escalar para suporte e gestor operacional]ES1 --> C1C1 -->|Sim| D[Estado: Submetida]D --> E[Distribuição automática ao Validador]E --> F{Validador disponível e sem conflito?}F -->|Conflito| F1[Registar impedimento e reatribuir]F1 --> EF -->|Indisponível| F2{SLA de atribuição excedido?}F2 -->|Não| EF2 -->|Sim| ES2[Escalar ao coordenador de validação]ES2 --> EF -->|Sim| H[Validação técnica e documental]H --> H1{Dependência externa ou dúvida crítica?}H1 -->|Sim| H2[Estado: Pendente de parecer]H2 --> H3{Parecer recebido no prazo?}H3 -->|Sim| HH3 -->|Não| ES3[Escalar ao responsável técnico ou jurídico]ES3 --> HH1 -->|Não| I{Decisão}I -->|Corrigir| J[Registar motivo, campos e prazo]J --> K[Estado: Correcção solicitada]K --> K1{Promotor responde no prazo?}K1 -->|Sim| L[Corrigir e voltar a submeter]L --> DK1 -->|Não| K2[Enviar lembrete e conceder tolerância]K2 --> K3{Tolerância excedida?}K3 -->|Não| K1K3 -->|Sim| K4[Arquivar por inactividade, com reabertura autorizada]I -->|Corrigir novamente| J2{Limite de ciclos excedido?}J2 -->|Não| JJ2 -->|Sim| ES4[Escalar ao coordenador para decisão assistida]ES4 --> II -->|Rejeitar| M[Registar fundamento e evidências]M --> N[Estado: Rejeitada]N --> N1{Promotor apresenta recurso no prazo?}N1 -->|Não| N2[Encerrar processo]N1 -->|Sim| N3[Encaminhar a instância distinta de recurso]N3 --> N4{Decisão de recurso}N4 -->|Manter rejeição| N2N4 -->|Reabrir| DI -->|Aprovar| P[Estado: Aprovada]P --> Q[Publicador verifica aprovação, integridade e conformidade]Q --> R{Condições de publicação satisfeitas?}R -->|Não corrigível| S[Devolver para correcção administrativa]S --> JR -->|Risco grave ou ilegalidade| ES5[Suspender fluxo e escalar à gestão e conformidade]ES5 --> ES6{Decisão extraordinária}ES6 -->|Regularizar| SES6 -->|Cancelar| N2R -->|Sim| T[Publicar ou programar publicação]T --> T1{Publicação concluída?}T1 -->|Falha técnica| T2[Reverter, preservar versão e abrir incidente]T2 --> ES1T1 -->|Sim| U[Estado: Publicada]U --> V{Denúncia, erro material ou risco superveniente?}V -->|Não| UV -->|Sim| W[Suspensão preventiva com motivo e prazo]W --> X[Notificar responsáveis e iniciar revisão urgente]X --> Y{Resultado da revisão}Y -->|Repor| UY -->|Corrigir| SY -->|Arquivar| Z[Estado: Arquivada]"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 283 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0292"",""pedido"":""Suporte técnico; gestor operacional se o SLA técnico for excedido."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 292 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0293"",""pedido"":""Código do erro, tentativa, versão, utilizador, data e correlação do incidente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 293 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0309"",""pedido"":""Número do ciclo, itens reincidentes e fundamentos."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 309 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0261"",""pedido"":""Suporte técnico; gestor operacional se o SLA técnico for excedido."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 261 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0262"",""pedido"":""Código do erro, tentativa, versão, utilizador, data e correlação do incidente."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 262 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0278"",""pedido"":""Número do ciclo, itens reincidentes e fundamentos."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 278 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos."",""estado"":""não implementado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",Correspondência documental preparada; protocolo de incidentes da submissão não implementado neste workflow.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-21,Recurso com instância independente e conservação da decisão original,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Responsabilidade appeal_reviewer de Validador e pedido de recurso no workflow_context existente. | [Workflow QA 10/10/2026] Recurso conserva rejeição/motivo; exige appeal_reviewer distinto do rejeitor e independente da autoria/organização; manter decisão ou reabrir, auditar e concluir tarefa existente.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","API de pedido prevista apenas rejected; decisão independente e percurso positivo de recurso não demonstrados. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Imobiliário19:rejeição24→pedido21→rejeitor24negado403/membroorg22negado403→revisor29reabre200→nova sessão21recupera. Decisão original permanece. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,"Fila/revisor distinto do decisor inicial, resposta/motivo/versionamento e recuperação visual. | [Workflow QA 10/10/2026] Visual; filas/designação/competências institucionais, políticas de prazo e instância ativa; manter decisão original e nenhuma autoridade real inferida.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.","Recurso não sobrescreve decisão; revisor distinto e autorizado decide com razão, sem publicar.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-21-USER-20261010,1,"[{""id"":""AUD-PROFILE-21-USER-20261010"",""pedido"":""Recurso com instância independente e conservação da decisão original"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Recurso não sobrescreve decisão; revisor distinto e autorizado decide com razão, sem publicar."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.",API de pedido prevista apenas rejected; decisão independente e percurso positivo de recurso não demonstrados. | [Workflow QA 10/10/2026] Imobiliário19:rejeição24→pedido21→rejeitor24negado403/membroorg22negado403→revisor29reabre200→nova sessão21recupera. Decisão original permanece.,"QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-22,"Prazos, tolerâncias e ciclos aprovados/configuráveis/versionados","Gestao de perfis investeMOZ v1.docx | parágrafo 284 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 311 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 313 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 326 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 337 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 524 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 525 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 526 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 527 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 528 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 253 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 280 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 282 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 295 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"policy_version nas atribuições e workflow, correction_cycles preservados; ausência de parâmetros não encerra processos automaticamente. | [Workflow QA 10/10/2026] SLA explicitamente unconfigured e due_at=null; preparação e tarefas continuam. Cliente não fixa prazo arbitrário. | [Instalação/cartografia QA 10/10/2026] Proposta SLA versionada:triagem2, revisõestécnica/jurídica10 emparalelo, parecer5, correção15, revisão5, editorial3 e recurso2+10 diasúteis; coordenação/responsabilidades e regras de pausa/lembrete/escalamento explícitas.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Instalação/cartografia QA 10/10/2026] AtivoREADONLY:030/040/09-190ausentes,0geometrias,flagsfalse/manifestopreservado; não ativado.","Versão de autorização profiles-v1-20261010 e correção auditadas; gestão/efeito de parâmetros ainda não implementados. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Tarefas e contexto recuperados com política/prazo nulos, sem tolerância/ciclos máximos inventados. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Instalação/cartografia QA 10/10/2026] profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.",parcial,"Tela/versionamento/governança e adaptação dos processos antigos; valores institucionais aprovados. | [Workflow QA 10/10/2026] Decisão concreta futura:qual política/versionamento de prazos,tolerância,ciclos e escalamento é aprovada? Motor/publicação de parâmetros pendentes; não bloqueia preparação. | [Instalação/cartografia QA 10/10/2026] D-SLA:aprovar/rever prazos, calendário/fuso, tolerância e terceirociclo, responsabilidades/suplentes. Nenhuma due_at ou atribuição real alterada; motor/visual do SLA apósdecisão.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.","Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0284;PROFILEV1-P0311;PROFILEV1-P0313;PROFILEV1-P0326;PROFILEV1-P0337;PROFILEV1-P0524;PROFILEV1-P0525;PROFILEV1-P0526;PROFILEV1-P0527;PROFILEV1-P0528;PROFILEOLD-P0253;PROFILEOLD-P0280;PROFILEOLD-P0282;PROFILEOLD-P0295,14,"[{""id"":""PROFILEV1-P0284"",""pedido"":""Diagrama 3 — Fluxo revisto com tratamento de falhas técnicas, indisponibilidade, conflitos, dependências externas, prazos, reincidência de correções, recurso, suspensão preventiva e escalamento hierárquico."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 284 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0311"",""pedido"":""Enviar lembrete e conceder período de tolerância."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 311 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0313"",""pedido"":""Notificações, prazos, motivo de arquivo e decisão de reabertura."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 313 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0326"",""pedido"":""SLA excedido sem resolução"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 326 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0337"",""pedido"":""Os prazos de atribuição, validação, correção, recurso, tolerância e resposta a incidentes, bem como o número máximo de ciclos de correção e os níveis de escalamento, devem ser configuráveis, versionados e aprovados pela gestão responsável. Cada alteração deve produzir registo de auditoria, indicar a data de entrada em vigor e preservar os parâmetros aplicáveis aos processos já iniciados, salvo decisão extraordinária devidamente fundamentada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 337 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0524"",""pedido"":""TC-GOV-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 524 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0525"",""pedido"":""Governação"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 525 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0526"",""pedido"":""Existe um processo em curso sujeito à versão atual dos prazos e limites operacionais."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 526 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0527"",""pedido"":""Um responsável autorizado aprova e publica uma nova versão dos parâmetros com data futura de entrada em vigor."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 527 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0528"",""pedido"":""A alteração fica auditada, os novos processos adotam a nova versão na data definida e o processo já iniciado conserva os parâmetros anteriores, salvo decisão extraordinária fundamentada e registada."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 528 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0253"",""pedido"":""Diagrama 3 — Fluxo revisto com tratamento de falhas técnicas, indisponibilidade, conflitos, dependências externas, prazos, reincidência de correções, recurso, suspensão preventiva e escalamento hierárquico."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 253 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0280"",""pedido"":""Enviar lembrete e conceder período de tolerância."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 280 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0282"",""pedido"":""Notificações, prazos, motivo de arquivo e decisão de reabertura."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 282 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0295"",""pedido"":""SLA excedido sem resolução"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 295 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Instalação/cartografia QA 10/10/2026] Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.","Versão de autorização profiles-v1-20261010 e correção auditadas; gestão/efeito de parâmetros ainda não implementados. | [Workflow QA 10/10/2026] Tarefas e contexto recuperados com política/prazo nulos, sem tolerância/ciclos máximos inventados. | [Instalação/cartografia QA 10/10/2026] HTTP 18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Instalação/cartografia QA 10/10/2026] Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:operação sem alterações DDL. Recursos/originais e15geometrias gravados somenteQA.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Instalação/cartografia QA 10/10/2026] Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Instalação/cartografia QA 10/10/2026] JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes. | [Instalação/cartografia QA 10/10/2026] Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados."
+AUD-PROFILE-23,"Auditoria integral, razões, origem e alertas de segurança",Gestao de perfis investeMOZ v1.docx | parágrafo 346 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"audit_events existente com ator/IP/tempo/correlação/política/razão e before-after relevantes; denegação sanitizada sem corpoauth. | [Workflow QA 10/10/2026] Auditoria existente recupera atores, razões, estados/versões/gates/hash e tarefas/recurso; razões de edição preservadas no histórico cifrado.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","HTTPs e fixture recuperam decisão/revogação/substituição e alerta administrativo; exportação minimizada não inclui segredos. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] Eventos workflow_submit/request_correction/review_gate/approve/publish/request_revision/suspend/appeal_reopen e revogações temporárias; nenhuma credencial/OTP/cookie exportados. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,"Cobertura dos fluxos ainda ausentes, exportação autorizada auditada, alertas operacionais e interface. | [Workflow QA 10/10/2026] Visual de filtros/exportações e comparação detalhada; auditabilidade de operações futuras ainda não implementadas. Composer audit apontou dois avisos preexistentes em league/commonmark (GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8); confirmar consumidores/configuração e corrigir emQA. Prova privada workflow-composer-audit.json; não são dos três pacotes Opis novos.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Cada decisão/crítica/negação guarda contexto rastreável e antes/depois aplicável; leitura/exportação não expõe segredos.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0346,1,"[{""id"":""PROFILEV1-P0346"",""pedido"":""Todos os eventos relevantes devem registar o utilizador, a data e hora, o endereço de origem, a ação, o objeto afetado, os valores anteriores e posteriores, o motivo e, quando aplicável, o processo de aprovação, a elevação temporária ou o incidente associado."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 346 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Cada decisão/crítica/negação guarda contexto rastreável e antes/depois aplicável; leitura/exportação não expõe segredos."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.",HTTPs e fixture recuperam decisão/revogação/substituição e alerta administrativo; exportação minimizada não inclui segredos. | [Workflow QA 10/10/2026] Eventos workflow_submit/request_correction/review_gate/approve/publish/request_revision/suspend/appeal_reopen e revogações temporárias; nenhuma credencial/OTP/cookie exportados.,"QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-24,MFA e segurança de sessão/autenticação sem contornar C37,"Gestao de perfis investeMOZ v1.docx | parágrafo 183 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 271 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 279 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 348 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 350 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 375 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 152 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 240 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 248 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 316 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 318 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 343 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Fortify existente, MFA normal, sessão QA/cookie isolados e epochs; proteção de MFA obrigatório em papéis críticos.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,"Doze contas confirmamMFA pelo servidor18097, nova sessão e recuperação30 comprovadas; C37conta18 não repetido/fechado. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.",parcial,"C37/interface, duração/reautenticação operacional e restantes consumidores/devices.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA.,P0,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0183;PROFILEV1-P0271;PROFILEV1-P0279;PROFILEV1-P0348;PROFILEV1-P0350;PROFILEV1-P0375;PROFILEOLD-P0152;PROFILEOLD-P0240;PROFILEOLD-P0248;PROFILEOLD-P0316;PROFILEOLD-P0318;PROFILEOLD-P0343,12,"[{""id"":""PROFILEV1-P0183"",""pedido"":""Configurar segurança e MFA"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 183 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0271"",""pedido"":""Executar ação privilegiada sem MFA válido"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 271 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0279"",""pedido"":""Token e sessões invalidados imediatamente."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 279 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0348"",""pedido"":""Autenticação multifator obrigatória para superutilizadores, validadores e publicadores, e recomendada para promotores."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 348 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0350"",""pedido"":""Sessões com expiração, revogação de dispositivos, limitação de tentativas, alertas de acesso anómalo e recuperação segura de conta."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 350 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0375"",""pedido"":""Conta pública simplificada; verificação reforçada e MFA para funções de maior risco."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 375 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0152"",""pedido"":""Configurar segurança e MFA"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 152 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0240"",""pedido"":""Executar ação privilegiada sem MFA válido"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 240 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0248"",""pedido"":""Token e sessões invalidados imediatamente."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 248 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0316"",""pedido"":""Autenticação multifator obrigatória para superutilizadores, validadores e publicadores, e recomendada para promotores."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 316 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0318"",""pedido"":""Sessões com expiração, revogação de dispositivos, limitação de tentativas, alertas de acesso anómalo e recuperação segura de conta."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 318 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0343"",""pedido"":""Conta pública simplificada; verificação reforçada e MFA para funções de maior risco."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 343 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.","Doze contas confirmamMFA pelo servidor18097, nova sessão e recuperação30 comprovadas; C37conta18 não repetido/fechado.",QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-25,"Interface responsiva, gravação segura, erros e acompanhamento","Gestao de perfis investeMOZ v1.docx | parágrafo 352 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 320 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Formulários/feedback existentes reutilizados; novas páginas de pedido/admin/auditoria e contexto organizacional. | [Workflow QA 10/10/2026] Editor declarativo comum/especializado, escolha de referências/recursos; ações após submissão abrem /view, edição privada por link autorizado; fila/estado/título privados distinguem ficha pública. | [Semântica QA 10/10/2026] Edidores declarativos detalhados pelo contrato do servidor, sem templates divergentes JS; erros canonical. junto aos controlos e acessibilidade; remoção do formulário núcleo duplicado no modo perfil. País/catálogo/autoridade/documentos selecionáveis; parcela/mapas reutilizados.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Semântica QA 10/10/2026] Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos.","PropsHTTP/compilação e TypeScript verificáveis; gravação/versionamentoAPI, nenhum navegador automatizável inventariado. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] PropsAPI e assetsQA:CRUD/ações/gates/prévia/tarefas; teste filtro necessidades/título privado; aprovação/pub com confirmação atual. NomePromotor QA — conta sintética21. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.",parcial,"Demonstração visual/acessibilidade, autosave e erros por campo nos contratos completos. | [Workflow QA 10/10/2026] Nenhum clique/render observado:dashboard→contratos/erros→workflow→recuperação ainda exige navegador; geometrias/parcela e objetos sem editor completo permanecem abertos. | [Semântica QA 10/10/2026] C37 e navegação/render/erros/seletores/ciclo por conta21 ainda pendentes; código e props não demonstram cliques. Preserva nova sessão e acesso direto às ferramentas.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.","Formulários recuperam dados, mostram ações/erros/pendências e não perdem resposta; navegação acessível por perfil.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0352;PROFILEOLD-P0320,2,"[{""id"":""PROFILEV1-P0352"",""pedido"":""Formulários responsivos e acessíveis, com linguagem simples, validação em linha, gravação automática de rascunhos e indicação do progresso."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 352 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Formulários recuperam dados, mostram ações/erros/pendências e não perdem resposta; navegação acessível por perfil."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0320"",""pedido"":""Formulários responsivos e acessíveis, com linguagem simples, validação em linha, gravação automática de rascunhos e indicação do progresso."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 320 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Formulários recuperam dados, mostram ações/erros/pendências e não perdem resposta; navegação acessível por perfil."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes.","PropsHTTP/compilação e TypeScript verificáveis; gravação/versionamentoAPI, nenhum navegador automatizável inventariado. | [Workflow QA 10/10/2026] PropsAPI e assetsQA:CRUD/ações/gates/prévia/tarefas; teste filtro necessidades/título privado; aprovação/pub com confirmação atual. NomePromotor QA — conta sintética21. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-26,"Privacidade, consentimento, consulta/correção/desativação","Gestao de perfis investeMOZ v1.docx | parágrafo 23 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 45 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 85 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 206 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 347 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 353 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 381 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 16 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 54 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 175 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 315 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 321 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 349 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,users/consents/documentos privados existentes; autorizações por pedido; remoção que destruiria titulares/histórico é negada.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Comprovativos privados por hash/autorização e não publicados; proteção de titular403; fluxo geral de desativação não ensaiado. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,"Consulta/correção/desativação preservando rastreabilidade e direitos aplicáveis, retenção/documentação por tipo.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0023;PROFILEV1-P0045;PROFILEV1-P0085;PROFILEV1-P0206;PROFILEV1-P0347;PROFILEV1-P0353;PROFILEV1-P0381;PROFILEOLD-P0016;PROFILEOLD-P0054;PROFILEOLD-P0175;PROFILEOLD-P0315;PROFILEOLD-P0321;PROFILEOLD-P0349,13,"[{""id"":""PROFILEV1-P0023"",""pedido"":""6. Segurança, privacidade e experiência do utilizador11"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 23 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0045"",""pedido"":""Consultar oportunidades públicas, guardar favoritos, gerir dados pessoais, subscrever alertas e acompanhar pedidos próprios."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 45 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0085"",""pedido"":""Gerir dados pessoais"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 85 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0206"",""pedido"":""Editar dados pessoais de outro utilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 206 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0347"",""pedido"":""6. Segurança, privacidade e experiência do utilizador"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 347 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0353"",""pedido"":""Recolha mínima de dados pessoais, consentimento explícito quando aplicável e mecanismos de consulta, correção e desativação da conta."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 353 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0381"",""pedido"":""A proposta segue as recomendações da OWASP para verificar permissões em cada pedido, aplicar o princípio do menor privilégio e evitar falhas de controlo de acesso, bem como as orientações do NIST para identidade digital baseada no risco, segurança, privacidade, interoperabilidade e experiência do utilizador. Fontes de referência: OWASP Authorization Cheat Sheet e NIST SP 800-63-4 Digital Identity Guidelines."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 381 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0016"",""pedido"":""Consultar oportunidades públicas, guardar favoritos, gerir dados pessoais, subscrever alertas e acompanhar pedidos próprios."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 16 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0054"",""pedido"":""Gerir dados pessoais"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 54 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0175"",""pedido"":""Editar dados pessoais de outro utilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 175 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0315"",""pedido"":""6. Segurança, privacidade e experiência do utilizador"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 315 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0321"",""pedido"":""Recolha mínima de dados pessoais, consentimento explícito quando aplicável e mecanismos de consulta, correção e desativação da conta."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 321 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0349"",""pedido"":""A proposta segue as recomendações da OWASP para verificar permissões em cada pedido, aplicar menor privilégio e evitar falhas de controlo de acesso, bem como a orientação do NIST para identidade digital baseada no risco, segurança, privacidade, interoperabilidade e experiência do utilizador. OWASP Authorization Cheat Sheet. NIST SP 800-63-4 Digital Identity Guidelines."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 349 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",Comprovativos privados por hash/autorização e não publicados; proteção de titular403; fluxo geral de desativação não ensaiado.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-27,Avaliar Keycloak antes de substituir Fortify,"Gestao de perfis investeMOZ v1.docx | parágrafo 357 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 325 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,Decisão arquitetural explícita em perfis-v1-reconciliacao.md; Fortify mantido e autorização funcional na aplicação.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,Código/schema confirmam Fortify e ausência de Keycloak; documentação oficial Keycloak/Laravel confrontada; necessidadeSSO/federação não demonstrada. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,concluído e demonstrado,Nenhuma lacuna desta avaliação restrita; eventual adoção futura exige necessidade/IDs/MFA/recuperação/migração aprovados.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Recomendação avaliada; decisão fundamentada preserva autenticação/IDs; não declara integraçãoKeycloak ativa.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0357;PROFILEOLD-P0325,2,"[{""id"":""PROFILEV1-P0357"",""pedido"":""Recomenda-se utilizar Keycloak como provedor central de identidade e autenticação, integrado com o backend do InvesteMoz. O Keycloak suporta gestão centralizada, federação, autenticação multifator e políticas finas que combinam RBAC, ABAC e controlos contextuais. As regras específicas — propriedade da oportunidade, tipo autorizado, organização e estado do fluxo — devem permanecer no serviço de autorização da aplicação, evitando dependência excessiva de um único produto. Fonte de referência: documentação oficial do Keycloak Authorization Services."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 357 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Recomendação avaliada; decisão fundamentada preserva autenticação/IDs; não declara integraçãoKeycloak ativa."",""estado"":""concluído e demonstrado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0325"",""pedido"":""Recomenda-se utilizar Keycloak como provedor central de identidade e autenticação, integrado com o backend do InvesteMoz. O Keycloak suporta gestão centralizada, federação, autenticação multifator e políticas finas que combinam RBAC, ABAC e controlos contextuais. As regras específicas — propriedade da oportunidade, tipo autorizado, organização e estado do fluxo — devem permanecer no serviço de autorização da aplicação, evitando dependência excessiva de um único produto. Keycloak Authorization Services, documentação oficial."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 325 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Recomendação avaliada; decisão fundamentada preserva autenticação/IDs; não declara integraçãoKeycloak ativa."",""estado"":""concluído e demonstrado"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Não aplicável: decisão documental restrita, sem substituição de autenticação.",Código/schema confirmam Fortify e ausência de Keycloak; documentação oficial Keycloak/Laravel confrontada; necessidadeSSO/federação não demonstrada.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Fortify mantido; não há integraçãoKeycloak instalada/declarada.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-28,Contratos especializados completos antes de submissão/aprovação/publicação,"Gestao de perfis investeMOZ v1.docx | parágrafo 341 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 427 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 428 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 429 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 430 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ v1.docx | parágrafo 431 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38
+Gestao de perfis investeMOZ.docx | parágrafo 309 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 395 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 397 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 398 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855
+Gestao de perfis investeMOZ.docx | parágrafo 399 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855",perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Schema normativo110defs/novecontratos e primeiro draftimobiliário anteriores; novos gates falham de forma controlada. | [Workflow QA 10/10/2026] Contrato canónico derivado do mesmo schema/condições normativas, sem alterar silenciosamente enums/IDs. Núcleo reutilizado, bindings/contactos/resources, submissão estrita e draft parcial. | [Semântica QA 10/10/2026] Contratos existentes enriquecidos e versionados sem substituir fonte/artifact110defs; rascunho admite ausência/null e grava/recupera; submissão estrita. Seis categorias demonstradas semanticamente nos cenários documentados; quatro aguardam versões modulares aprovadas. | [Instalação/cartografia QA 10/10/2026] Propostas inativas concession/financing/supply/other baseadas em§25.4(P2101–2105), reutilizam campos,documentos,geo eworkflow existentes; decisões regra/fundamento/efeito individualizadas.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Semântica QA 10/10/2026] Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos. | [Instalação/cartografia QA 10/10/2026] AtivoREADONLY:030/040/09-190ausentes,0geometrias,flagsfalse/manifestopreservado; não ativado.","Submissão realdraft15 responde422 com lacuna do contratoCreate; versões públicas não alteradas. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] 10drafts recuperados,6contratos completos estruturalmente aceites/4bloqueados por perfil;6verificados novamente no snapshot atual. Source.json false é histórico da extração, runtime rastreado no relatório. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado. | [Instalação/cartografia QA 10/10/2026] profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.",parcial,"Adaptadores canónicos, camposUI/regras/vínculos/evidências especializados e ciclo completo sem fixtureestado. | [Workflow QA 10/10/2026] Semântica §25/objetos opacos, Response integral, grillas específicas e quatro perfis aprovados; visual, publicação de todos os contratos com dados/provas aplicáveis ainda não demonstrada. | [Semântica QA 10/10/2026] Quais versões imutáveis de perfil/campos/documentos/gates são aprovadas para concession,financing,supply,other? Sem inventar contratos. Visual e condições jurídicas/Response integral permanecem parciais. | [Instalação/cartografia QA 10/10/2026] Perfis não aprovados/nem carregadospelo motor; guardar/editar4drafts anterior provado, submissão/revisão/publicação mantidas bloqueadas. Seis contratos completos na interface ainda não demonstrados.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,PROFILEV1-P0341;PROFILEV1-P0427;PROFILEV1-P0428;PROFILEV1-P0429;PROFILEV1-P0430;PROFILEV1-P0431;PROFILEOLD-P0309;PROFILEOLD-P0395;PROFILEOLD-P0397;PROFILEOLD-P0398;PROFILEOLD-P0399,11,"[{""id"":""PROFILEV1-P0341"",""pedido"":""Cada tipo de oportunidade possui requisitos, campos, documentos, validadores e fluxo próprios."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 341 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0427"",""pedido"":""TC-PR-01"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 427 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0428"",""pedido"":""Promotor"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 428 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0429"",""pedido"":""Organização e tipo autorizados"",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 429 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0430"",""pedido"":""Criar rascunho, anexar documentos e submeter."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 430 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEV1-P0431"",""pedido"":""Oportunidade criada na organização correta e estado alterado para Submetida."",""fontes"":[""Gestao de perfis investeMOZ v1.docx | parágrafo 431 | SHA256 f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0309"",""pedido"":""Cada tipo de oportunidade possui requisitos, campos, documentos, validadores e fluxo próprios."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 309 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0395"",""pedido"":""TC-PR-01"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 395 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0397"",""pedido"":""Organização e tipo autorizados"",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 397 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0398"",""pedido"":""Criar rascunho, anexar documentos e submeter."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 398 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""},{""id"":""PROFILEOLD-P0399"",""pedido"":""Oportunidade criada na organização correta e estado alterado para Submetida."",""fontes"":[""Gestao de perfis investeMOZ.docx | parágrafo 399 | SHA256 283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855""],""aceitacao"":""Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada."",""estado"":""parcial"",""variantes"":""Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Semântica QA 10/10/2026] Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes. | [Instalação/cartografia QA 10/10/2026] Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.","Submissão realdraft15 responde422 com lacuna do contratoCreate; versões públicas não alteradas. | [Workflow QA 10/10/2026] 10drafts recuperados,6contratos completos estruturalmente aceites/4bloqueados por perfil;6verificados novamente no snapshot atual. Source.json false é histórico da extração, runtime rastreado no relatório. | [Semântica QA 10/10/2026] QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, 5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:investment_project#30:published; real_estate#31:published; land_rights#32:approved; business_sale#33:published; business_partnership#34:published; franchise#35:published; concession#36:draft; financing#37:draft; supply#38:draft; other#39:draft. Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado. | [Instalação/cartografia QA 10/10/2026] HTTP 18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Semântica QA 10/10/2026] opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada. | [Instalação/cartografia QA 10/10/2026] Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:operação sem alterações DDL. Recursos/originais e15geometrias gravados somenteQA.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Semântica QA 10/10/2026] 10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada. | [Instalação/cartografia QA 10/10/2026] Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Semântica QA 10/10/2026] RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente. | [Instalação/cartografia QA 10/10/2026] JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes. | [Instalação/cartografia QA 10/10/2026] Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados."
+AUD-PROFILE-29,Reconciliar permissões administrativas legadas sem retirada automática,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,manage-portal preservado para registroslegados; novos privados não autorizados pela allowlist; nenhuma conta ativa promovida/revogada.,Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,AtivoREADONLY:rolesv1 ausentes/flagfalse; gestores2/13 existentes; fixture nega acesso legado ao novo privado sem perfil. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,dependente de decisão concreta,"Pergunta para futuraativação: que funções dos gestores ativos devem corresponder a Validador, Publicador, Auditor ou administração controlada? Quem serão os dois titulares e o aprovador da cerimónia?","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.",Correspondência aprovada conserva contas/história e deixa diferenças/permissões explícitas; nenhuma revogação ativa automática.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-29-USER-20261010,1,"[{""id"":""AUD-PROFILE-29-USER-20261010"",""pedido"":""Reconciliar permissões administrativas legadas sem retirada automática"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Correspondência aprovada conserva contas/história e deixa diferenças/permissões explícitas; nenhuma revogação ativa automática."",""estado"":""dependente de decisão concreta"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",AtivoREADONLY:rolesv1 ausentes/flagfalse; gestores2/13 existentes; fixture nega acesso legado ao novo privado sem perfil.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-30,Contas sintéticas por perfil e demonstração permitida/negada,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Doze contas sintéticasQA, duas organizações e quatro representações; contas antigas preservadas. | [Workflow QA 10/10/2026] PromotorQA21 claramente identificado, tipos autorizados por pedido/decisão independente. Validador24 reatribuído explicitamente, Publicador25 e instância sintética29 separados.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.","profiles-v1-http-qa.json e recovery-audit: permitido/negado, rolesmúltiplos, troca/revogação/nova sessão sem divulgarcredenciais. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] NormalFortify/MFA na18097; cenário18,19 e recuperação dos10drafts; negar self/multirole e revogar permissões temporárias. Não escolher titulares/responsáveis reais. QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.",parcial,"Demonstração visual por perfil;24 agora revogado e28 substituído, não apresentar esses atores como papéis ainda ativos. | [Workflow QA 10/10/2026] C37 e visual por cada perfil; novos processos/contratos ainda não cobertos. QA não equivale à instalação ativa.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.",Cada perfil tem ensaio positivo/negativo e recuperação noutra sessão; revogação/múltiplos papéis não contornam autorização.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-30-USER-20261010,1,"[{""id"":""AUD-PROFILE-30-USER-20261010"",""pedido"":""Contas sintéticas por perfil e demonstração permitida/negada"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Cada perfil tem ensaio positivo/negativo e recuperação noutra sessão; revogação/múltiplos papéis não contornam autorização."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.","profiles-v1-http-qa.json e recovery-audit: permitido/negado, rolesmúltiplos, troca/revogação/nova sessão sem divulgarcredenciais. | [Workflow QA 10/10/2026] NormalFortify/MFA na18097; cenário18,19 e recuperação dos10drafts; negar self/multirole e revogar permissões temporárias. Não escolher titulares/responsáveis reais.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
+AUD-PROFILE-31,"Instalação, disponibilização e reversão dos perfis separadas",Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Migration040000guardada, flagQAtrue/ativofalse, fingerprints das instalações existentes incluem o código de autorização. | [Workflow QA 10/10/2026] Código/Composer3novos pacotes, assets exclusivosQA, guardas e migrações existentes; recursos030000/profiles040000 precedem disponibilização das flags. Novos contratos não criam tabelas próprias. | [Instalação/cartografia QA 10/10/2026] Instalador autenticado040000: prévia, schema e dependências 030000 + 020000, hash/reason/MFA, idempotência UUID e auditoria transacional; bootstrap separado e explícito reutiliza PortalSuperusers. Schema parcial bloqueado; rollback vazio/reinstalação e falha de auditoria recuperados em teste isolado.","Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue. | [Workflow QA 10/10/2026] Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa. | [Instalação/cartografia QA 10/10/2026] AtivoREADONLY:030/040/09-190ausentes,0geometrias,flagsfalse/manifestopreservado; não ativado.","QA:4tabelas,users1/opportunities3colunas,1função2triggers; ativoREADONLYausente. Baseline18tabelas originais preservadas; assetsativosSHAigual. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível. | [Workflow QA 10/10/2026] AtivoREADONLY:020000sim/030000não/040000não/flagsfalse/0geom; QA393privadas,18conjuntosoriginais preservados/MFA18intacto/manifativo753... . QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas. | [Semântica QA 10/10/2026] Provasdeledger/colunas/definição:dashboard-active-readonly.json e opportunity-semantic-environment-qa.json;preservação18coleções/MFA18/manifestoativo:profiles-v1-preservation-qa.json. | [Instalação/cartografia QA 10/10/2026] profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.",parcial,"Mecanismo autenticado de instalação040000 e bootstrap ativo auditável, nova prova backup/restauro/compatibilidade/reversão apósvisuais, ativação não autorizada. | [Workflow QA 10/10/2026] Aceitação visual, fechar editores/gates prioritários e fixar candidata; mecanismo040000ativo/authedbootstrap ainda não completo; renovarbackup/restauro dessa revisão, sem repetir instalações nem importar fixtures sintéticas. | [Instalação/cartografia QA 10/10/2026] Visual da instalação/bootstrap, designação real dos dois titulares e política da recuperação simultânea; backup da futura candidata e do ativo após demonstração visual. Schema040 jáQA, sem reinstalação destrutiva ou novos titulares no servidor18097.","Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente. | [Workflow QA 10/10/2026] Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna. | [Semântica QA 10/10/2026] Leitura ativaREADONLY10/10:020000eBalcão07/190000+08/120000instalados;030000não;040000não;09/190000prepare_investor_pathausente(ledger/2colunas/definição). QA03/04/09-190instalados;definição19etapaspublicada61000919-0000-4000-8000-000000000001 SHAe0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf. 09/190000nãofoi substituída:continuanecessária paraativo e não se repeteQA. 030/040semdependênciaDDL190;190dependeBalcão/journeys/steps/questionnaire_versions;workflowusa020+030+040+tasks/catalogue. Planofuturo:visual/candidata→backup/restaurofrescos→códigoflagsfalse→030autenticada→040instalador/bootstrapautenticadosaindaemfalta→190apenasfaltantesvia/management/balcao-install→dadosreais/perfis→cartografiaprivadaidempotente→flagspercurso/oportunidades→publicaçãoseparada. 0fixturesQAnoativo;readytrueépreparação;semativaçãoautorizada;reversãodesativaflags/preservahistóricoourestaurabackupverificado,nãodropusado.",Instalar somente ausentes com prévia/provas/replay; designar dupla de forma controlada; flag não é instalação; rollback conserva dados e nega acesso aos privados.,P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-31-USER-20261010,1,"[{""id"":""AUD-PROFILE-31-USER-20261010"",""pedido"":""Instalação, disponibilização e reversão dos perfis separadas"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Instalar somente ausentes com prévia/provas/replay; designar dupla de forma controlada; flag não é instalação; rollback conserva dados e nega acesso aos privados."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes. | [Workflow QA 10/10/2026] Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto. | [Instalação/cartografia QA 10/10/2026] Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.","QA:4tabelas,users1/opportunities3colunas,1função2triggers; ativoREADONLYausente. Baseline18tabelas originais preservadas; assetsativosSHAigual. | [Workflow QA 10/10/2026] AtivoREADONLY:020000sim/030000não/040000não/flagsfalse/0geom; QA393privadas,18conjuntosoriginais preservados/MFA18intacto/manifativo753... . | [Instalação/cartografia QA 10/10/2026] HTTP 18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.","QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes. | [Workflow QA 10/10/2026] Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados. | [Instalação/cartografia QA 10/10/2026] Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:operação sem alterações DDL. Recursos/originais e15geometrias gravados somenteQA.","Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados. | [Workflow QA 10/10/2026] Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto. | [Instalação/cartografia QA 10/10/2026] Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.",Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente. | [Workflow QA 10/10/2026] Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas. | [Instalação/cartografia QA 10/10/2026] JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes. | [Instalação/cartografia QA 10/10/2026] Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados."
+AUD-PROFILE-32,Arquivo/exclusão/restauro do Promotor versus gestor legado,Pedido direto do responsável10/10/2026 nesta conversa,perfis e oportunidades,/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*,"Decisão antes do código:Promotorv1 apenas solicita; Publicador decidearquivo; lifecyclegestorlegado preservado para antigos, privado não herda.",Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.,HTTP21pedidoarquivo persiste sem mudar draft; endpointlifecycle privado403; gestorC43 anterior conserva percurso independente. | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.,parcial,Interfacepedido/decisãopublicador com caso válido e critério de conservação; não prometer exclusão/restauro não concedidos pela v1.,"Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.","Promotor solicita com razão, sem arquivar/apagar/restaurar; decisor autorizado registraresultado; legado mantém direitos identificados.",P1,Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.,AUD-PROFILE-32-USER-20261010,1,"[{""id"":""AUD-PROFILE-32-USER-20261010"",""pedido"":""Arquivo/exclusão/restauro do Promotor versus gestor legado"",""fontes"":[""Pedido direto do responsável10/10/2026 nesta conversa""],""aceitacao"":""Promotor solicita com razão, sem arquivar/apagar/restaurar; decisor autorizado registraresultado; legado mantém direitos identificados."",""estado"":""parcial"",""variantes"":""Reconciliação funcional com v1 e auditoria existente."",""modulo"":""perfis e oportunidades""}]","Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.",HTTP21pedidoarquivo persiste sem mudar draft; endpointlifecycle privado403; gestorC43 anterior conserva percurso independente.,QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.,Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.,Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.,"Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes."
diff --git a/docs/investmoz/v2/auditoria-portal/perfis-v1-reconciliacao.md b/docs/investmoz/v2/auditoria-portal/perfis-v1-reconciliacao.md
new file mode 100644
index 00000000..99f4985f
--- /dev/null
+++ b/docs/investmoz/v2/auditoria-portal/perfis-v1-reconciliacao.md
@@ -0,0 +1,523 @@
+# Perfis e oportunidades — reconciliação da versão 1
+
+
+## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em 2026-10-10T10:32:41+00:00: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **91 pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `profile_restore_20261010_104956_test:55441` → **295 tabelas com linhas/hashes iguais e 69 ficheiros fisicamente recuperados por hash**; todos os ficheiros referenciados recuperados por hash. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+
+
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco conserva a revisão semântica anterior; o estado atual está no início do documento; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Perfis v1: resultado do lote em QA — 10/10/2026
+
+A v1 foi lida integralmente: 530 parágrafos, confrontados com os 471 do exemplar anterior, AGENTS, auditoria, código, schema PostgreSQL e configuração. Fortify, contas, documentos, relações, IDs, classificações, histórico, cinco fases e 19 etapas foram preservados. Keycloak foi avaliado como recomendação; não há necessidade de SSO/federação demonstrada para substituir Fortify neste lote. A aceitação das fontes oficiais permanece intacta.
+
+**A mesma matriz contém 3.386 requisitos/linhas e 6.838 ocorrências de origem.** Os 3.354 requisitos e 5.830 referências anteriores foram conservados. Acrescentaram-se 32 requisitos verificáveis, os 1.001 parágrafos dos dois exemplares e sete referências diretas da reconciliação. Parágrafos de estrutura e tabelas são referências, não pedidos independentes. Inventário: 591 exemplares, versões e anexos; 202 ficheiros acessíveis nesta varredura, incluindo 12 marcadores de bloqueio Office preservados por bytes/hash.
+
+| Estado canónico | Requisitos | Ocorrências |
+| --- | ---: | ---: |
+| parcial | 3228 | 6371 |
+| não implementado | 146 | 454 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+O sexto concluído é apenas **AUD-PROFILE-27**, a avaliação arquitetural de Keycloak. Não encerra autenticação visual nem uma integração externa. **AUD-OP-03 passa a parcial**, pelas regras e transições novas; o workflow integral continua aberto.
+
+QA: **http://127.0.0.1:18097**, destino efetivamente verificado `desk_restore_20261009_174726_test:55441`, com guarda antes de escrita. Foram preparadas 12 contas sintéticas, com MFA configurado e confirmado normalmente por Fortify, duas organizações e quatro representações. O ensaio comprovou:
+
+- Dashboard do Promotor → links devolvidos pela interface → criação do rascunho 15 → gravação idempotente → nova sessão MFA → recuperação → edição pelo outro Promotor autorizado da mesma organização. Autor e ID permanecem; outra organização, tipo não autorizado e transferência de organização recebem 403.
+- Quatro pedidos de Promotor, comprovativos privados com ClamD real e hash recuperado, acompanhamento noutra sessão e aprovação independente. Rejeição pode registar conferências falsas sem inventar validação. Auditor com outro papel continua sem escrita operacional.
+- Revogação do Validador 24: sessão antiga recebe 401; nova sessão MFA autentica, mas o papel já não autoriza. Inicialização da dupla 27/28 pelo terceiro aprovador 29; substituição atómica 28→30; dupla atual 27/30, terceiro negado, replay negado e sessão anterior invalidada.
+- Recuperação do titular 30 por código Fortify noutra sessão, sem desativar MFA; código consumido não autentica. Desativação de MFA, eliminação e mudança de email do titular são recusadas. Auditor recupera e exporta metadados filtrados, sem snapshots privados.
+- Consumidores territoriais do Promotor corrigidos para rotas autorizadas: 11 províncias, **Cabo Delgado** selecionada, guardada e recuperada com o mesmo ID/nome; uma área geométrica devolvida pela API. O desenho no navegador continua por demonstrar.
+
+**Continuam abertos:** C37, cenários A/B e C43 na interface; contratos especializados completos e vínculos canónicos; submissão/aprovação/publicação positivas, agendamento e versão pública; filas dos coordenadores, pareceres, incidentes de suporte, decisões de recurso, SLA e governança; âmbito provincial de autorização; tokens/dispositivos; privacidade e todas as operações documentais por tipo/perfil. A submissão real do rascunho 15 responde 422 controlado por contrato Create incompleto. Revisão/correção positiva foi ensaiada com uma fixture explicitamente submetida, não com uma submissão real.
+
+API e persistência estão demonstradas nos escopos acima. Interface preparada e compilada; nenhum navegador automatizável foi inventariado, portanto não há aceitação visual. TypeScript, build QA e PHPStan passaram; 14 testes específicos, com 446 asserções, passaram. A contagem não substitui a prova por requisito.
+
+Manifesto QA demonstrado: `22947d5c47487137b9e37138f29322d99181c7d0cb0bc655dba67fd2e444ae80`. Manifesto ativo preservado: `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`. Não há revisão candidata fixada enquanto faltar a aceitação visual.
+
+Acumulação com a permissão administrativa antiga foi reconciliada antes da alteração: uma conta com atribuição v1 não usa a criação legada para contornar organização/tipo; a revogação não restaura automaticamente privilégio antigo mais amplo. Auditor com permissão legada continua sem escrita administrativa. Testes de compatibilidade comprovam as negações; gestores sem atribuições v1 conservam as funções anteriores. Caso C49 adicionado, sem alteração de privilégios ativos.
+
+Preservação por ID/colunas originais comprovada em 18 tabelas, incluindo conta 18, documentos e auditoria; manifesto ativo inalterado. Ativo consultado exclusivamente em transação READ ONLY (`investemoz:5432`): perfis 040000 ausentes e flag desativada; 020000 instalada, 030000/percurso ausentes, zero geometrias. **Nenhuma escrita ou alteração de privilégios ativos.** QA mantém 393 geometrias privadas; faltam 31 distritos e 157 postos, já nomeados. Publicação de camadas é separada.
+
+Evidências sanitizadas: `profiles-v1-http-qa.json`, `profiles-v1-mfa-enrollment-qa.json`, `profiles-v1-recovery-audit-qa.json`, `profiles-v1-current-version-qa.json`, `profiles-v1-preservation-qa.json`, `profiles-v1-reconciliation-proof.json`, `profiles-v1-final-qa.xml` e `profiles-v1-build-qa.log`, em `storage/app/private/investmoz-v2/portal-audit/`. Credenciais, cookies, segredos e códigos não constam dos relatórios.
+
+[Correspondência por requisito](perfis-v1-reconciliacao.md), [roteiro manual](roteiro-manual-perfis-v1.md), [backlog](backlog.md), [ativação e reversão](plano-ativacao.md). Relatório e backlog também disponíveis no servidor QA, com autenticação, em `/qa-auditoria/relatorio-executivo` e `/qa-auditoria/backlog`.
+
+
+### Correspondência derivada da mesma matriz
+
+Esta projeção não é outro inventário editável. Fontes e versões integrais permanecem no CSV.
+
+**AUD-PROFILE-01 — Seis perfis sobre identidades existentes, com RBAC e ABAC** (parcial).
+
+Implementação: PortalProfileAccess; users/Fortify, organizations/memberships, quatro atribuições operacionais e dupla controlada; público derivado de conta verificada.
+
+Prova: Doze atores normais MFA e consultas por perfil no servidor QA; schema ligado às entidades canónicas.
+
+Lacuna/próxima ação: Âmbito provincial ainda não modelado; migração reconciliada dos gestores legados e aceitação visual por perfil.
+
+Aceitação: Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado.
+
+**AUD-PROFILE-02 — Utilizador público: consulta, favoritos/alertas e pedidos próprios** (parcial).
+
+Implementação: Capacidades públicas existentes; pedido próprio de Promotor reutiliza conta verificada.
+
+Prova: Conta20: dashboard→pedido, criação403 e consulta de pedido alheio403; favoritos/alertas não ensaiados neste lote.
+
+Lacuna/próxima ação: Demonstrar favoritos/alertas e todos os pedidos pessoais na interface; alternativa de confirmação por telefone da v1 ainda não implementada, verificação de email existente preservada.
+
+Aceitação: Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público.
+
+**AUD-PROFILE-03 — Solicitar perfil de Promotor com representação, tipos e comprovativos** (parcial).
+
+Implementação: PortalProfileAdministration::request; documentos canónicos próprios/hash/scan, chave idempotente, âmbito individual ou organização representada.
+
+Prova: Contas21/22/23/31: quatro pedidos, replay sem duplicação, recuperação noutra sessão, quatro comprovativos sintéticos com ClamD real e recuperação por hash.
+
+Lacuna/próxima ação: Verificação visual do formulário, submissão de tipos adicionais e regras institucionais de comprovativos por representação.
+
+Aceitação: Pedido guarda representação/tipos/comprovativos, fica recuperável e não concede o papel por si só.
+
+**AUD-PROFILE-04 — Decisão independente do pedido de Promotor e tipos aprovados** (parcial).
+
+Implementação: Fila administrativa, consulta privada dos comprovativos por VerifiedDocumentBinary, versão e atestações auditadas; sem autoaprovação.
+
+Prova: Super27 consulta originais por hash e aprova quatro pedidos de outros atores; teste nega decisão própria e regista rejeição com verificações falsas sem inventar confirmação.
+
+Lacuna/próxima ação: Aceitação visual da fila e decisões; não foram validadas identidades reais, apenas documentos sintéticos QA.
+
+Aceitação: Somente aprovador distinto com MFA confirma identidade/representação/documentos e concede os tipos efetivamente pedidos e aprovados.
+
+**AUD-PROFILE-05 — Navegação por perfil a partir do dashboard** (parcial).
+
+Implementação: ProfileNavigation e props de autorização partilhadas; páginas existentes reutilizadas em /minhas-oportunidades.
+
+Prova: DashboardHTTP21 devolve Minhas oportunidades/Nova oportunidade;20 devolve Solicitar perfil; ensaio segue os URLs devolvidos, sem depender de rota conhecida previamente.
+
+Lacuna/próxima ação: Cliques, renderização, responsividade e resultado visível no navegador; C37 não fechado.
+
+Aceitação: Promotor autorizado descobre lista/criação no dashboard; os outros descobrem pedido e acompanhamento sem obter criação.
+
+**AUD-PROFILE-06 — Edição organizacional por outros Promotores e âmbito pessoal exclusivo** (parcial).
+
+Implementação: OpportunityManagement/Resources reutilizados; owner_user_id preservado, contributors e membership de escrita em servidor.
+
+Prova: Autor21 cria oportunidade15; colega22 autorizado edita, recuperação mantémID/autor;23 fora da organização403. Seletores/mapas mudam para endpointsautorizadosv1:11províncias, seleçãoCaboDelgado gravada/recuperada noutra sessão com geometriaAPI. Teste de representação revogada nega escrita.
+
+Lacuna/próxima ação: Percurso visual e coedição dos recursos por operação; restrições provinciais permanecem separadas.
+
+Aceitação: Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado.
+
+**AUD-PROFILE-07 — Autorizações por tipo e representação sem transferência silenciosa** (parcial).
+
+Implementação: Tipos em atribuições e pedidos; organização imutável na edição, autor/workflow/status proibidos no payload.
+
+Prova: HTTP22: mudança para tipo não aprovado403 e transferência de organização403; fixture testa isolamento de tipos.
+
+Lacuna/próxima ação: Demonstrar todos os contratos especializados e seus campos/validadores; seleção do tipo não os encerra.
+
+Aceitação: Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão.
+
+**AUD-PROFILE-08 — Estados, razões, versões e dependências reais do workflow** (parcial).
+
+Implementação: OpportunityProfileWorkflow reutiliza códigos/management_version/etag/audit_events; revisão, correção, parecer, rejeição/suspensão/arquivo e pedidos segregados.
+
+Prova: HTTP: pedido de arquivo guarda e mantémdraft, submissão422 com lacuna explícita; fixture submetida inicia revisão, pede correção e recupera edição.
+
+Lacuna/próxima ação: Submissão completa, aprovação/publicação, incidentes e conservação de versão pública ainda não demonstradas; fixture não é submissão real.
+
+Aceitação: Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa.
+
+**AUD-PROFILE-09 — Impedir aprovação própria, conflitos de organização e publicação pelo aprovador** (parcial).
+
+Implementação: Autor, contributors e membership da organização impedem revisão; publicação verifica aprovador da mesma versão; autorizações rechecadas sob lock.
+
+Prova: Teste autor com Promotor+Validador+Publicador continua403; regras editor/representação verificadas no serviço.
+
+Lacuna/próxima ação: Publicação real permanece bloqueada pelo contrato; testar ciclo completo e reatribuição independente com versão aprovada real.
+
+Aceitação: Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos.
+
+**AUD-PROFILE-10 — Acumulação de papéis com negação prevalecente** (parcial).
+
+Implementação: Auditor nega escrita operacional; Super exige papel operacional mais elevação independente; papéis não se somam para ultrapassar restrições.
+
+Prova: Conta31 Promotor+Validador+Auditor lê e recebe403 na edição;27 Super sem Promotor/elevação recebe403 na criação. Fixture com papéis v1 e allowlist legada: criação fora do âmbito403, dashboard sem criação legada; Auditor nega escrita administrativa. Revogação/expiração não restaura permissão legada automaticamente.
+
+Lacuna/próxima ação: Demonstração visual e combinações operacionais adicionais com elevação aprovada.
+
+Aceitação: A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor.
+
+**AUD-PROFILE-11 — Validador: revisão atribuída, MFA, correções e decisão** (parcial).
+
+Implementação: Papel validator com âmbito/tipos e responsabilidades compatíveis; MFA confirmado exigido na atribuição e recente na operação.
+
+Prova: 24 aprovado inicialmente, aprovação de draft409, revogado depois; fixture independente revisa/corrige e recupera nova versão; semMFA403.
+
+Lacuna/próxima ação: Fila de atribuição e completude normativa, decisão positiva integral e interface.
+
+Aceitação: Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem.
+
+**AUD-PROFILE-12 — Publicador: versão aprovada, suspensão/arquivo e segregação** (parcial).
+
+Implementação: Papel publisher, MFA recente, independência; conteúdo técnico não editável; publicar bloqueado se completude/versão faltam.
+
+Prova: 25 publica draft409; fixture confirma estado incompatível; todos os atos positivos de publicação integral continuam pendentes.
+
+Lacuna/próxima ação: Publicação e agendamento, revisão de divulgação, suspensão urgente/retificação e prova da versão pública.
+
+Aceitação: Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa.
+
+**AUD-PROFILE-13 — Auditor: consulta filtrada/exportação e ausência de escrita** (parcial).
+
+Implementação: /perfis/auditoria usa audit_events existentes, filtros e JSON minimizado; Auditor conserva impedimento de escrita.
+
+Prova: 26 recupera substituição filtrada e exporta metadados sem snapshots privados;20 recebe403;31 multirrole edição403.
+
+Lacuna/próxima ação: Interface, exportação ampliada autorizada por classificação e consulta dos restantes domínios administrativos.
+
+Aceitação: Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor.
+
+**AUD-PROFILE-14 — Superutilizador: administração controlada e elevação temporária** (parcial).
+
+Implementação: PortalSuperusers/Administration; MFA recente, motivo, aprovação independente e validade15min; aprovador deve continuar na dupla.
+
+Prova: 27 administra pedidos/papéis, autoaprovação403, criação sem papel403; elevação API preparada, ainda sem ato operacional positivo completo.
+
+Lacuna/próxima ação: Demonstração da elevação completa, expiração, scope/action exatos e interface de administração.
+
+Aceitação: Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação.
+
+**AUD-PROFILE-15 — Exatamente dois Superutilizadores: inicialização e substituição atómica** (parcial).
+
+Implementação: Dupla singleton ligada a users, CHECK distintos, triggerDELETE/TRUNCATE, versão/lock, aprovação e atualização única.
+
+Prova: Inicialização27/28 pelo29; terceira atribuição422; substituição28→30 com aprovação28 independente de27, dupla27/30; replay409, sessão28invalidada. TriggerDELETE testado.
+
+Lacuna/próxima ação: Interface, testes concorrentes em sessões simultâneas e cerimónia ativa com titulares reais ainda não designados.
+
+Aceitação: Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade.
+
+**AUD-PROFILE-16 — Recuperar acesso preservando MFA e dupla** (parcial).
+
+Implementação: Códigos de recuperação Fortify e substituição independente; bloqueio de desativaçãoMFA, mudançaemail/eliminação de titular.
+
+Prova: 30 recupera sessãoMFA noutra sessão pelo códigoFortify; reutilização422 sem autenticação; DELETE-MFA/conta e PATCHemail403.
+
+Lacuna/próxima ação: Procedimento institucional quando ambos perdem todos os meios; aceitação visual e guarda local dos códigos sem os transmitir.
+
+Aceitação: Recuperação normal mantém MFA e dois titulares; código consumido não autentica; emergência não é desativaçãoMFA ou key:generate.
+
+**AUD-PROFILE-17 — Revogação imediata com histórico e invalidação de sessões/tokens** (parcial).
+
+Implementação: Atribuição retida, revision de autorização por conta, remember_token revogado; adaptação sessions/personal_access_tokens quando presentes.
+
+Prova: 24 antigo cookie401; nova sessãoMFA autentica mas acesso de papel403;28 substituído igual. Histórico original preservado.
+
+Lacuna/próxima ação: Tokens pessoais não instalados/ensaiados no alvo, dispositivos/integradores e interface por consumidor.
+
+Aceitação: Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões.
+
+**AUD-PROFILE-18 — Validade, reavaliação por inatividade e documentação expirada** (parcial).
+
+Implementação: starts_at/expires_at/revoked_at consultados a cada pedido; atribuições documentadas sem cache de autorização.
+
+Prova: Fixture de papel expirado não autoriza; MFA antigo não permite decisão.
+
+Lacuna/próxima ação: Revalidação/inatividade/expiração documental, parâmetros aprovados e avisos; não inventar prazos.
+
+Aceitação: Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados.
+
+**AUD-PROFILE-19 — Coordenadores de validação/publicação e pareceres técnico-jurídicos** (não implementado).
+
+Implementação: Responsabilidades mapeadas e compatibilidade por papel validadas; entidades existentes de tarefa/auditoria a reutilizar.
+
+Prova: Responsabilidade validation_coordinator em Auditor422; papéis/responsabilidades armazenáveis, filas e reatribuições não implementadas.
+
+Lacuna/próxima ação: Implementar filas/atribuição, conflito, disponibilidade, parecer e escalamento sem novos perfis ou identidades.
+
+Aceitação: Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável.
+
+**AUD-PROFILE-20 — Suporte técnico, incidentes e preservação da submissão** (não implementado).
+
+Implementação: Balcão/tarefas/audit_events existentes; suporte mapeado sem acesso documental automático; nenhum gestor fictício.
+
+Prova: Correspondência documental preparada; protocolo de incidentes da submissão não implementado neste workflow.
+
+Lacuna/próxima ação: Incidentes recuperáveis, suporte atribuído, falha de submissão/ficheiro sem perda, alertas e estados próprios.
+
+Aceitação: Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos.
+
+**AUD-PROFILE-21 — Recurso com instância independente e conservação da decisão original** (parcial).
+
+Implementação: Responsabilidade appeal_reviewer de Validador e pedido de recurso no workflow_context existente.
+
+Prova: API de pedido prevista apenas rejected; decisão independente e percurso positivo de recurso não demonstrados.
+
+Lacuna/próxima ação: Fila/revisor distinto do decisor inicial, resposta/motivo/versionamento e recuperação visual.
+
+Aceitação: Recurso não sobrescreve decisão; revisor distinto e autorizado decide com razão, sem publicar.
+
+**AUD-PROFILE-22 — Prazos, tolerâncias e ciclos aprovados/configuráveis/versionados** (parcial).
+
+Implementação: policy_version nas atribuições e workflow, correction_cycles preservados; ausência de parâmetros não encerra processos automaticamente.
+
+Prova: Versão de autorização profiles-v1-20261010 e correção auditadas; gestão/efeito de parâmetros ainda não implementados.
+
+Lacuna/próxima ação: Tela/versionamento/governança e adaptação dos processos antigos; valores institucionais aprovados.
+
+Aceitação: Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo.
+
+**AUD-PROFILE-23 — Auditoria integral, razões, origem e alertas de segurança** (parcial).
+
+Implementação: audit_events existente com ator/IP/tempo/correlação/política/razão e before-after relevantes; denegação sanitizada sem corpoauth.
+
+Prova: HTTPs e fixture recuperam decisão/revogação/substituição e alerta administrativo; exportação minimizada não inclui segredos.
+
+Lacuna/próxima ação: Cobertura dos fluxos ainda ausentes, exportação autorizada auditada, alertas operacionais e interface.
+
+Aceitação: Cada decisão/crítica/negação guarda contexto rastreável e antes/depois aplicável; leitura/exportação não expõe segredos.
+
+**AUD-PROFILE-24 — MFA e segurança de sessão/autenticação sem contornar C37** (parcial).
+
+Implementação: Fortify existente, MFA normal, sessão QA/cookie isolados e epochs; proteção de MFA obrigatório em papéis críticos.
+
+Prova: Doze contas confirmamMFA pelo servidor18097, nova sessão e recuperação30 comprovadas; C37conta18 não repetido/fechado.
+
+Lacuna/próxima ação: C37/interface, duração/reautenticação operacional e restantes consumidores/devices.
+
+Aceitação: Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA.
+
+**AUD-PROFILE-25 — Interface responsiva, gravação segura, erros e acompanhamento** (parcial).
+
+Implementação: Formulários/feedback existentes reutilizados; novas páginas de pedido/admin/auditoria e contexto organizacional.
+
+Prova: PropsHTTP/compilação e TypeScript verificáveis; gravação/versionamentoAPI, nenhum navegador automatizável inventariado.
+
+Lacuna/próxima ação: Demonstração visual/acessibilidade, autosave e erros por campo nos contratos completos.
+
+Aceitação: Formulários recuperam dados, mostram ações/erros/pendências e não perdem resposta; navegação acessível por perfil.
+
+**AUD-PROFILE-26 — Privacidade, consentimento, consulta/correção/desativação** (parcial).
+
+Implementação: users/consents/documentos privados existentes; autorizações por pedido; remoção que destruiria titulares/histórico é negada.
+
+Prova: Comprovativos privados por hash/autorização e não publicados; proteção de titular403; fluxo geral de desativação não ensaiado.
+
+Lacuna/próxima ação: Consulta/correção/desativação preservando rastreabilidade e direitos aplicáveis, retenção/documentação por tipo.
+
+Aceitação: Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público.
+
+**AUD-PROFILE-27 — Avaliar Keycloak antes de substituir Fortify** (concluído e demonstrado).
+
+Implementação: Decisão arquitetural explícita em perfis-v1-reconciliacao.md; Fortify mantido e autorização funcional na aplicação.
+
+Prova: Código/schema confirmam Fortify e ausência de Keycloak; documentação oficial Keycloak/Laravel confrontada; necessidadeSSO/federação não demonstrada.
+
+Lacuna/próxima ação: Nenhuma lacuna desta avaliação restrita; eventual adoção futura exige necessidade/IDs/MFA/recuperação/migração aprovados.
+
+Aceitação: Recomendação avaliada; decisão fundamentada preserva autenticação/IDs; não declara integraçãoKeycloak ativa.
+
+**AUD-PROFILE-28 — Contratos especializados completos antes de submissão/aprovação/publicação** (parcial).
+
+Implementação: Schema normativo110defs/novecontratos e primeiro draftimobiliário anteriores; novos gates falham de forma controlada.
+
+Prova: Submissão realdraft15 responde422 com lacuna do contratoCreate; versões públicas não alteradas.
+
+Lacuna/próxima ação: Adaptadores canónicos, camposUI/regras/vínculos/evidências especializados e ciclo completo sem fixtureestado.
+
+Aceitação: Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada.
+
+**AUD-PROFILE-29 — Reconciliar permissões administrativas legadas sem retirada automática** (dependente de decisão concreta).
+
+Implementação: manage-portal preservado para registroslegados; novos privados não autorizados pela allowlist; nenhuma conta ativa promovida/revogada.
+
+Prova: AtivoREADONLY:rolesv1 ausentes/flagfalse; gestores2/13 existentes; fixture nega acesso legado ao novo privado sem perfil.
+
+Lacuna/próxima ação: Pergunta para futuraativação: que funções dos gestores ativos devem corresponder a Validador, Publicador, Auditor ou administração controlada? Quem serão os dois titulares e o aprovador da cerimónia?
+
+Aceitação: Correspondência aprovada conserva contas/história e deixa diferenças/permissões explícitas; nenhuma revogação ativa automática.
+
+**AUD-PROFILE-30 — Contas sintéticas por perfil e demonstração permitida/negada** (parcial).
+
+Implementação: Doze contas sintéticasQA, duas organizações e quatro representações; contas antigas preservadas.
+
+Prova: profiles-v1-http-qa.json e recovery-audit: permitido/negado, rolesmúltiplos, troca/revogação/nova sessão sem divulgarcredenciais.
+
+Lacuna/próxima ação: Demonstração visual por perfil;24 agora revogado e28 substituído, não apresentar esses atores como papéis ainda ativos.
+
+Aceitação: Cada perfil tem ensaio positivo/negativo e recuperação noutra sessão; revogação/múltiplos papéis não contornam autorização.
+
+**AUD-PROFILE-31 — Instalação, disponibilização e reversão dos perfis separadas** (parcial).
+
+Implementação: Migration040000guardada, flagQAtrue/ativofalse, fingerprints das instalações existentes incluem o código de autorização.
+
+Prova: QA:4tabelas,users1/opportunities3colunas,1função2triggers; ativoREADONLYausente. Baseline18tabelas originais preservadas; assetsativosSHAigual.
+
+Lacuna/próxima ação: Mecanismo autenticado de instalação040000 e bootstrap ativo auditável, nova prova backup/restauro/compatibilidade/reversão apósvisuais, ativação não autorizada.
+
+Aceitação: Instalar somente ausentes com prévia/provas/replay; designar dupla de forma controlada; flag não é instalação; rollback conserva dados e nega acesso aos privados.
+
+**AUD-PROFILE-32 — Arquivo/exclusão/restauro do Promotor versus gestor legado** (parcial).
+
+Implementação: Decisão antes do código:Promotorv1 apenas solicita; Publicador decidearquivo; lifecyclegestorlegado preservado para antigos, privado não herda.
+
+Prova: HTTP21pedidoarquivo persiste sem mudar draft; endpointlifecycle privado403; gestorC43 anterior conserva percurso independente.
+
+Lacuna/próxima ação: Interfacepedido/decisãopublicador com caso válido e critério de conservação; não prometer exclusão/restauro não concedidos pela v1.
+
+Aceitação: Promotor solicita com razão, sem arquivar/apagar/restaurar; decisor autorizado registraresultado; legado mantém direitos identificados.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+Fonte integral: `Gestao de perfis investeMOZ v1.docx`, versão 1.0, 10/10/2026, 530 parágrafos, SHA256 `f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38`. Exemplar anterior: `Gestao de perfis investeMOZ.docx`, 471 parágrafos, SHA256 `283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855`. São especificações funcionais do responsável, não diplomas oficiais. Fontes, versões e divergências ficam na matriz existente; não se cria outra matriz.
+
+## Decisões documentadas antes da alteração em QA
+
+1. **Edição pela organização:** o responsável decidiu nesta conversa permitir outros Promotores autorizados da organização. Representação ativa de escrita em `memberships` e autorização para o tipo continuam obrigatórias. A autoria original e todos os editores ficam registados; não se transfere propriedade silenciosamente. Sem organização, o âmbito individual permanece exclusivamente do titular da conta.
+2. **Arquivo/exclusão:** a v1 §3.2 atribui ao Promotor apenas solicitar suspensão/arquivo. Não concede exclusão nem restauro. O percurso C43 anterior de gestor continua para os registos legados; não se converte esse gestor em Promotor nem em Superutilizador. Os novos registos sujeitos à v1 usam pedidos e decisões separadas.
+3. **Gestores existentes:** `manage-portal` é atualmente verificação de email mais lista `portal.managers`; não é um catálogo de seis perfis. Preserva-se a lista e o histórico. A lista não permite editar, validar, publicar, arquivar ou administrar perfis v1 por si só. Na futura ativação, a migração das permissões administrativas existentes exige reconciliação explícita, sem retirar privilégios ativos automaticamente.
+4. **Identidade:** reutilizam-se `users`, Fortify, sessões, `organizations`, `memberships`, `documents` e `audit_events`. Atribuições de papéis e pedidos são dados de autorização ligados a essas entidades, não novas contas nem um fornecedor paralelo de identidade. O perfil público é derivado de conta confirmada. Papéis de âmbito organizacional não equivalem a `memberships.role`.
+5. **Acumulação:** negação prevalece. Auditor mantém operações de oportunidades somente de leitura; Superutilizador necessita de papel operacional mais elevação temporária independente para operar. Autor, editor ou representante da organização não aprova a oportunidade. Quem aprova uma versão não a publica.
+6. **Pessoa singular:** âmbito pessoal usa `organization_id=null` mais titular da conta, sem fabricar uma organização. Empresa/entidade/associação/parceiro exigem organização existente e representação de escrita. Aprovação documental não cria automaticamente organizações, vínculos ou autorização de outros tipos.
+7. **Publicação:** contratos especializados incompletos continuam a impedir submissão/aprovação/publicação. Criar e guardar rascunho é independente. Nenhuma revisão interna constitui licença, DUAT, financiamento ou decisão externa.
+8. **Superutilizadores:** não se escolhem titulares reais. Inicialização QA usa duas contas sintéticas distintas, verificadas e com MFA confirmado. A dupla é uma única entidade transacional; substituição atualiza os dois titulares numa operação, com versão, MFA recente, consentimento independente, auditoria e invalidação do acesso anterior. Recuperação usa Fortify/MFA/códigos de recuperação existentes ou substituição aprovada; nunca desativa MFA nem usa segredo/chave ativos em QA.
+
+9. **Acumulação com a allowlist legada:** uma conta que recebe um papel v1 em QA não usa a permissão legada para contornar a organização, o tipo ou o impedimento de escrita do Auditor. Escrita de oportunidades legadas por essa conta exige reconciliação explícita; o percurso v1 usa os seus registos sujeitos à política. Gestores sem papéis v1 conservam as funções anteriores. Nenhuma conta ativa recebe ou perde automaticamente um papel. Auditor com permissão administrativa legada continua sem escrita administrativa; dados pessoais próprios e pedidos pessoais mantêm o tratamento existente.
+
+## Correspondência dos perfis
+
+| Perfil v1 | Entidades e controlos reutilizados | Âmbito e regra |
+| --- | --- | --- |
+| Utilizador público | `users`, verificação Fortify, favoritos/alertas/pedidos existentes | Dados e pedidos próprios; catálogo público; solicita perfil, sem criar oportunidades |
+| Promotor | `users`, `memberships`, autorização por tipo, OpportunityManagement/Resources | Organização representada e tipos aprovados; pessoal apenas próprio; guarda e responde a correções |
+| Validador | Papel atribuído a `users`, oportunidades/auditoria existentes | Âmbito/tipo, MFA, independência do autor/editores/organização; revisão sem publicação |
+| Publicador | Papel atribuído a `users`, versão aprovada e auditoria | MFA, aprovação independente da versão; não edita conteúdo técnico |
+| Auditor | Papel atribuído a `users`, `audit_events` e configurações | Leitura e exportação minimizada; negação de escrita operacional prevalece |
+| Superutilizador | Dupla controlada ligada a `users`, Fortify/MFA, auditoria | Administração de perfis; operação exige elevação independente e papel operacional |
+
+## Responsabilidades adicionais — não são novos perfis
+
+| Responsabilidade citada | Correspondência proposta | Limite |
+| --- | --- | --- |
+| Coordenador de validação | Validador com responsabilidade `validation_coordinator` explicitamente atribuída | Atribuir/reencaminhar; mesmos impedimentos para decidir |
+| Responsável técnico/jurídico | Validador com âmbito e responsabilidade técnica/jurídica | Parecer documentado, não decisão externa presumida |
+| Suporte técnico | Superutilizador com responsabilidade técnica, ou tarefa atribuída a suporte no mecanismo existente | Diagnóstico de incidente; não ganha acesso ao conteúdo ou decisão por receber tarefa |
+| Gestor operacional/direção/conformidade | Superutilizador administrativo; Auditor para controlo sem escrita | Escalar e auditar; não ultrapassa segregação operacional |
+| Instância de recurso | Validador com responsabilidade `appeal_reviewer`, distinto de autor, editores e decisor inicial | Decisão de recurso preserva decisão original; não publica |
+| Coordenador de publicação | Publicador com responsabilidade de coordenação | Reatribuir publicação; não aprova conteúdo |
+
+Estas correspondências técnicas não nomeiam responsáveis reais. Responsáveis institucionais, SLA, tolerância, limites de ciclos e política documental por tipo precisam de valores aprovados e versionados antes de automatizar escalamentos. Não se inventam prazos. Enquanto ausentes, devem ficar visíveis e sem encerramento automático.
+
+## Implementação e compatibilidade
+
+O incremento é condicionado por `portal.profile_access_enabled`, desativado por omissão. QA mantém `manage-portal` para funções legadas e separa os novos controlos. Registos antigos não recebem organização, autor, tipo ou novos estados por inferência. Os códigos existentes `in_review`, `information_pending`, `needs_information`, `approved`, `rejected`, `published`, `suspended` e `archived` são preservados; os rótulos novos não renumeram os roteiros, as cinco fases ou as 19 etapas.
+
+A criação/edição reutiliza o rascunho existente. A autorização verifica no servidor representação, tipo, estado, validade, revogação, autoria/intervenientes, conflitos e MFA. Os links “Minhas oportunidades”, “Nova oportunidade” e “Solicitar perfil de Promotor” são derivados dessas regras, não autoridade em si. Pedidos ficam recuperáveis pelo titular e revistos por outra pessoa autorizada.
+
+## Keycloak
+
+É recomendação arquitetural, não dependência deste lote. A [documentação oficial do Keycloak](https://www.keycloak.org/docs/latest/authorization_services/index.html) descreve políticas RBAC/ABAC; a aplicação continua responsável por aplicar decisões aos seus recursos. Laravel já oferece [policies e gates](https://laravel.com/framework/docs/12.x/authorization). A decisão deste lote é manter Fortify: a necessidade de federação/SSO de vários sistemas não foi demonstrada no ambiente atual. Uma futura troca precisa de prova de necessidade, correspondência estável de IDs, compatibilidade MFA/sessões, operação e recuperação independentes, e migração aprovada. Não se substitui autenticação para resolver regras de organização/tipo/estado.
+
+## Ativação e reversão
+
+Este lote não autoriza a base ativa. Antes de ativar: concluir demonstração visual por perfil, reconciliar permissões legadas e titulares reais, fixar revisão, renovar backup/restauro de base e ficheiros, aplicar instalação autenticada apenas se ausente e disponibilizar a flag separadamente. Instalações anteriores de gestão/recursos/percurso não se repetem. Desativar a flag preserva atribuições, pedidos e história; registos novos não podem ficar expostos às rotas legadas. Reversão de schema só antes de dados novos; depois requer restauro reconciliado ou preservação das tabelas. Não revogar privilégios ativos automaticamente.
+
+Estado inicial deste registo: diagnóstico documental e decisão de compatibilidade; demonstrações do incremento serão acrescentadas após os ensaios. C37 e os percursos visuais A/B permanecem pendentes.
diff --git a/docs/investmoz/v2/auditoria-portal/plano-ativacao.md b/docs/investmoz/v2/auditoria-portal/plano-ativacao.md
index 552e5c78..8e08c7f5 100644
--- a/docs/investmoz/v2/auditoria-portal/plano-ativacao.md
+++ b/docs/investmoz/v2/auditoria-portal/plano-ativacao.md
@@ -1,5 +1,146 @@
# Plano consolidado de ativação — lote 3
+
+## Sequência reconciliada — preparada, não executada no ativo
+
+**030000 → 040000 → 190000** mantém-se. QA já tem as três; **não repetir instalações QA**. No ativo lido READ ONLY, as três extensões estão ausentes; Balcão07/190000 eorientação08/120000 estão instalados. A extensão **09/190000 não foi substituída**: faltam ledger,duascolunas e definição19etapas. Fonte:dashboard-active-readonly.json eopportunity-semantic-environment-qa.json.
+
+| Ordem | Ação futura, efeito econtagem prevista | Dependência / reversão |
+| --- | --- | --- |
+| 0 | Demonstração visual de C37, QA21 e A/B e correções → fixar candidata, hashes, manifesto e configuração → backup da base + originais + runtime e chave estável → restauro emQA nova, tabelas/bytes/acessos comparados. | QA backup deste lote não é backup ativo nem candidata definitiva. Ativação continua fora da autorização. |
+| 1 | Disponibilizar código/Composer/build compatíveis, flagsfalse eURLs preservadas. | Não retirar privilégios reais ou migraridentidades automaticamente. Reverter flags/build/código compatível preservando dados novos. |
+| 2 —030 | GETprévia→POST `/management/opportunity-resources-install`, hash/confirm/MFA/provas atuais, sóse ausente/coerente. **três coleções+metadado cifra;zero documentos importados/publicados.** | Base020/documentos existentes. Não drop apósuso; restaurar/reconciliar backup em vez de apagar originais. |
+| 3 —040 | GETprévia→POST `/management/profile-install`; **quatro tabelas + uma coluna em users + três em opportunities,zero contas, atribuições ou flags.** BootstrapPOST `/management/profile-install/bootstrap` é **separado**:duas contas explicitamente designadas; um terceiro gestor com MFA aprova. | Instalador exige020+030/schema/organização/auditoria, hash ebackup/restauro atuais. Idempotência eDDL/ledger/auditoria atómicos. Schema parcial bloqueia aplicação; down apenassemqualqueruso/contexto/revisão/histórico. Recuperação deMFA simultânea exigeD-R1,sembootstraprepetido. |
+| 4 —09/190 | GETprévia→POST `/management/balcao-install`, sómigraçãofaltante: **duas colunas + uma definição publicada de 19 etapas / cinco fases; zero dossiers automáticos.** | BaseBalcão/orientação jáinstaladas: não repetir. SemdepDDLde040,masordem operacional preservada. Template eversões usados imutáveis; reverterdisponibilização,preservar snapshots/roteiros. |
+| 5 —cartografia | GETprévia→POST `/management/territory-geometry-import`, níveis1→2→3 ehash/idempotência. **408 correspondências candidatas** se cadastro/hash coincidem:11/133/264;ativo0na leitura. **173 pendentes** não importadas. | Fontes/hash/pai/nome/código vinculados;resultado/contagem medida no alvo,semfusões ougeometrias inventadas. Reversão só lotesnovos nãoalterados/usados,postos→distritos→províncias comaudit;seFK/uso,preservar/reconciliar,nãoforçar. |
+| 6 —disponibilização | Aprovar perfis/reconciliação depermissões reais econfiguração; habilitar navegação/editores/percurso porincremento comprovado. **zero fixtures QA no ativo.** | I1–I3 não concluídos semA/B/interface. Contratos4categorias eSLA sóapósdecisão própria. Importação não ativa cálculo fiscal. |
+| 7 —publicação | Revisão dedivulgação eação do Publicador por versão; **camadas cartográficas públicas são ação separada** daimportação. | Aprovaçãointerna≠acessorestrito≠catálogopúblico≠decisãoexterna. Desabilitar publicação/flags antes derestauro;preservar originais,consentimentos eauditoria. |
+
+Sharedcode/fingerprint muda:renovar provas da revisão ealvo;ready=true não instala,não escolhe titulares,não publica enão disponibiliza percurso. Guarda ativa/QA conferida antes decada escrita futura. A prova040 emschema vazio foi isolada; no servidorQA jáusado sóoperação sem alterações, auditada.
+
+
+
+## Ativação reconciliada: 030000, 040000 e **09/190000** — nenhuma execução no ativo
+
+A omissão de **2026_10_09_190000_prepare_investor_path** na sequência anterior foi um erro documental; a extensão **continua necessária e não foi substituída**. Não confundir com **2026_10_07_190000_create_internal_virtual_desk**, que já está instalada no ativo.
+
+| Recurso | QA restaurada:55441 | Ativo investemoz:5432, READ ONLY | Evidência |
+| --- | --- | --- | --- |
+| Gestão020000 | Instalada | Instalada | Ledger/schema anteriores preservados |
+| Balcão07/190000 e orientação08/120000 | Instalados | Ambos no ledger | Leitura efetiva das migrações, sem boot de sessão ativa |
+| Recursos09/030000 | Instalada | Ausente | Tabelas e ledger; não repetirQA |
+| Perfis10/040000 | Instalada | Ausente | Tabelas/verificaçãoQA; nunca instalada no ativo neste trabalho |
+| Percurso09/190000 | **Ledger + duas colunas + definição publicada** | **Ledger ausente; duas colunas ausentes; nenhuma definição** | `dashboard-active-readonly.json`, `opportunity-semantic-environment-qa.json` |
+
+DefiniçãoQA `61000919-0000-4000-8000-000000000001`, publicada, SHA256 **e0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf**. Duas colunas: `investor_journeys.path_definition_id` e `journey_steps.path_detail`. Mantém cinco fases e rastreabilidade das19etapas; não renumera/reescreve os roteiros existentes. Recurso preparado/definição publicada não demonstra A/B na interface.
+
+Dependências verificadas no código: **030000** usa oportunidades/documentos existentes e cria três coleções de recursos; **040000** acrescenta quatro tabelas de autorização/auditoria, uma coluna de revisão em users e três colunas em opportunities, preservando identidades/histórico; não usa as colunas de190000. **190000** usa investor_journeys/journey_steps/questionnaire_versions e depende da baseBalcão/orientação incluída no instalador. Não existe dependência DDL entre030/040 e190; disponibilizar o workflow requer020+030+040 e tasks/catalogue existentes; disponibilizar o percurso integrado requer190 e as capacidades instaladas/configuradas. Os fingerprints incluem código comum de perfis: alterar o código invalida provas antigas de readiness, sem converter isso numa dependência de schema.
+
+| Ordem futura | Ação concreta e efeito / contagem esperada | Dependência e reversão |
+| --- | --- | --- |
+| 0 | Incorporar visualC37/Promotor21/A-B; corrigir falhas e fixar revisão/manifesta/configuração. Renovar dumpDB+ficheirosoriginaisprivados+chaveestável e restauroverificado numa novaQA. | Candidata ainda não fixada; provas antigas não são backup dessa revisão. Nunca key:generate indiscriminado. |
+| 1 | Disponibilizar código/Composer/bundle após aprovação de ativação, flagsfalse. | Nesta análise só buildQA foi atualizado; manifestativo preservado. Reversão para código/build anteriores e flagsfalse; assegurar compatibilidade de leitura. |
+| 2 | **030000**, se ledger/schema realmente ausentes: préviaGET e aplicaçãoPOST autenticada `/management/opportunity-resources-install` com hash/confirm. | Três coleções resource e metadado de cifra; **zero documentos/dados publicados/importados**. Base020/documentos existentes. Downgrade destructive recusado se originais cifrados usados. |
+| 3 | **040000**, se ausente: instalar quatro tabelas/colunas através de mecanismo autenticado e bootstrap/recuperação da dupla, ainda por implementar paraativo. | Não substituir por migrateglobal/configmanual para contornar guarda. **Zero contas/grants QA** noativo. Titulares/reconciliação de permissões reais precisam de decisão explícita. Código independente de190. |
+| 4 | **09/190000**, se ausente: préviaGET e aplicaçãoPOST autenticada `/management/balcao-install`; instalador seleciona só migrações faltantes. | BaseBalcão07/190000 e orientação08/120000 jáconstamdoativo: não repetir. **Duas colunas + uma definição publicada**, se não existir equivalente; **zero dossiers/journeys criados automaticamente**. Versões publicadas imutáveis. |
+| 5 | Configurar catálogos/responsabilidades reais e instalar apenas contratos modulares aprovados; comparar IDs/citações/versões. | A autoridade sintética QA3e1ff315… e atores21–31 não são dados deativação. Sem alteração automática de valores legados. |
+| 6 | Importação cartográfica autenticada privada `/management/territory-geometry-import`: prévia/correspondências/hash→aplicação idempotente→auditoria. | QA393=11províncias+128distritos+254postos; ativo0naúltimaleitura. **393 candidatas inequívocas**, sujeitas à prévia da revisão e aos mesmos IDs;188pendentes(31/157), sem criar geometrias falsas. Contagem final deve ser medida no alvo. Reversão por lote/metadados e histórico, sem apagar cadastros. |
+| 7 | Ativar flags de perfis/oportunidades e percurso separadamente, testar navegação completa e permissões. | 030/040 antesdoscontratos/workflow;190antesdodisponibilizarpercurso; C37/visual/A-B não encerrados. Preparação paralela e acesso direto continuam. |
+| 8 | **Publicar camadas, oportunidades ou documentos como ações separadas e explícitas**. | Nenhuma instalação/importação publica automaticamente; publicação não ativa cálculo fiscal. Usar decisões/evidências/hash atuais e autorização de divulgação. |
+
+Reversão: desativarflags/voltarbundle compatível e conservar originais/auditoria. Migrações usadas não devem ser eliminadas por rollback genérico;190recusadownquandohápercurso,030recusacomcifrados,040preservaperfil/oportunidade. Quando necessária reversão de dados, usar o restauroverificado da candidata com reconciliação das escritas posteriores. **ready=true é preparação; não instalação, ativação nem aceitação funcional.**
+
+
+
+## Sequência reconciliada de disponibilização futura — não executada
+
+Leitura ativa de 10/10: PostgreSQL `investemoz:5432`, transação READ ONLY, seis oportunidades publicadas; 020000 instalada, 030000/040000/percurso ausentes, flags desativadas, zero geometrias. Build ativo preservado. A revisão candidata **não está fixada**; `ready=true` e fingerprints anteriores não autorizam nem demonstram instalação.
+
+| Ordem | Ação e efeito previsto | Dependência / reversão |
+| --- | --- | --- |
+| 0 | Incorporar visual C37/C43/A/B e workflow, corrigir falhas; fixar revisão, configuração e manifestos. Renovar backup DB + ficheiros privados/originais + chave estável e provar restauro numa nova QA isolada. | Provas anteriores preservadas, sem as apresentar como restauro desta revisão. Não gerar nova chave. |
+| 1 | Disponibilizar código e dependências compatíveis, flags desligadas. Composer adiciona `opis/json-schema 2.4.1`, `opis/string 2.1.0`, `opis/uri 1.1.0`; zero atualizações/remoções preexistentes. | Não importar contas, classificações, contactos ou documentos sintéticos QA. Reverter código/assets compatíveis, preservando payloads/histórico. |
+| 2 | Não repetir 020000. Se 030000 continuar ausente, usar prévia/aplicação autenticada `/management/opportunity-resources-install`: três tabelas, uma coluna documental, uma função e três triggers previstos. | Backup/restauro confirmado; hashes/contagens verificados no estado real; não publica nem habilita o percurso. |
+| 3 | Preparar e testar o mecanismo autenticado 040000: quatro tabelas, uma coluna de utilizador, três de oportunidade, uma função e dois triggers previstos; dupla inicial/substituição independente. | Aplicação atual demonstrada exclusivamente QA. Instalação/bootstrap ativo autenticado ainda pendente; titulares reais não definidos. Não remover privilégios ativos automaticamente. |
+| 4 | Configurar referências/contactos/hierarquia, perfis/tipos/representação, responsabilidades e MFA; quatro contratos modulares apenas após aprovação da versão. | Reutilizar dados mestres reais. As referências sintéticas de ensaio não resolvem cadastros ativos vazios. SLA permanece indeterminado até política aprovada. |
+| 5 | Importação cartográfica autenticada, privada e idempotente; se ativo permanecer zero e correspondências iguais, até **393 = 11 províncias + 128 distritos + 254 postos**. Esperados 581 = 11/159/411; pendentes 188 = 0/31/157, nomes no relatório de correspondências. | Prévia → correspondências inequívocas → scan/hash → aplicar → auditoria; nenhuma localização/conta/perímetro de projeto inventado. Reversão pelo lote preserva origem/uso/histórico. **Publicação de camadas é ação separada.** |
+| 6 | Disponibilizar flags/assets/navegação aprovados e o percurso I1–I3 pela instalação existente, sem repetir ações já presentes. Publicar cada oportunidade separadamente, com aprovação/hash/prévia/âmbito. | Cinco fases/19 etapas preservadas, dossier privado separado. Voltar flags a false limita disponibilização; manter guardas de confidencialidade para novos dados. Não executar down destrutivo após uso. |
+
+Após uso, reverter por configuração compatível, suspensão/arquivo autorizado ou compensação auditada; não eliminar decisões, documentos, consentimentos, relações ou originais. Restauro global exige reconciliar alterações posteriores ao backup. Este plano não contém aprovação de ativação nem declaração de instalação ativa.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Sequência consolidada: instalações, disponibilização e reversão — 10/10/2026
+
+Preparação exclusivamente em QA. Nenhuma ativação autorizada e nenhuma revisão candidata fixada. As provas `ready` anteriores são históricas: os fingerprints incluem agora as regras de perfis, portanto não comprovam esta revisão nem instalação funcional.
+
+1. Incorporar os ensaios visuais C37/C43/A/B, perfis e consumidores; corrigir falhas; fixar revisão, manifestos e configuração. Reconciliar permissões legadas e titulares reais. Completar os contratos antes de disponibilizar submissão/aprovação/publicação.
+2. Renovar backup da base, originais, ficheiros e configuração/chaves após fixar a revisão. Restaurar numa nova QA guardada e comparar IDs, relações, hashes, schema, compatibilidade e reversão. Usar as contagens reais do momento. A cópia de 09/10 não é apresentada como backup renovado desta candidata.
+3. **Gestão 020000:** já instalada no ativo; não repetir. Atalhos C43 e primeiro rascunho imobiliário não exigem essa instalação. Disponibilização dos atalhos por `PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`, separada do schema; preservar gestores verificados e funções legadas reconciliadas.
+4. **Recursos 030000:** se ausente, prévia e aplicação autenticadas por GET/POST `/management/opportunity-resources-install`, com provas atuais. Esperado: três tabelas de associação, uma coluna em documents, uma função e três triggers; zero originais/recursos criados automaticamente. ClamD/GD/WebP são dependências das operações binárias afetadas. Instalação não confirma scans, divulgação ou publicação.
+5. **Perfis 040000:** falta concluir o mecanismo autenticado de instalação e o bootstrap ativo em QA. A migration guardada está preparada, sem autorização para execução ativa indiscriminada. Esperado: quatro tabelas de autorização ligadas às entidades existentes; uma coluna em users e três em opportunities; uma função e dois triggers. **Zero contas, atribuições ou titulares reais criados automaticamente.** Depende da gestão 020000; recursos 030000 são necessários para os respetivos consumidores. A cerimónia designa dois titulares reais com MFA e terceiro aprovador independente, sem converter a allowlist antiga. `PORTAL_PROFILE_ACCESS_ENABLED` é disponibilização separada. QA já instalada: não repetir migration ou bootstrap; dupla sintética atual 27/30.
+6. **Balcão e percurso:** instalar apenas dependências ausentes pelo mecanismo autenticado existente; 190000 prepara o percurso e múltiplos investimentos. Preservar cinco fases e 19 etapas. Instalação não disponibiliza nem conclui I1–I3; flags, assets, rotas e cenários A/B visuais têm provas próprias. Não depende de CRM externo.
+7. **Importação cartográfica:** prévia, correspondências, hash e aplicação autenticada privada/idempotente/auditável, usando territórios existentes. QA: 393 de 581 geometrias esperadas — províncias 11/11, distritos 128/159, postos 254/411; pendentes 0/31/157, com os 188 nomes em correspondencias-cartograficas.md. A prévia ativa calcula a interseção inequívoca do alvo, sem copiar contagens QA cegamente. Publicação das camadas é outra ação. Importação não ativa cálculos fiscais; fonte oficial aceite não requer nova validação de credibilidade.
+8. Somente após futura autorização ativa, verificar código/compilação/cache/cookies/guards, contagens antes/depois, auditoria, originais, versão pública e recuperação dos percursos no alvo aprovado.
+
+**Reversão:** desativar flags específicas e interromper novas operações, mantendo código de autorização compatível com os privados. Não regressar a código que os exponha. 040000 recusa `down` se há dados/pedidos/dupla/histórico; depois de uso, preservar tabelas ou reconciliar restauro numa janela autorizada. Revogações e substituições permanecem rastreáveis. Não restaurar um backup antigo apagando dados posteriores. 030000 só reverte antes de uso; percurso e importação usam as reversões existentes, preservando relações/originais. Reversão da publicação de camadas é independente da importação.
+
+Fingerprints preparados, sem fixação de candidata:
+
+- profiles: `5ad5c2bb4989f7d5356115b4c2adaa20ddf1def87694a3291205114e1e677ae3`
+- management: `0aa282e5cc8d9cde72e326b1cebd6814966097026c2cadbeca23ced8fdb2518a`
+- resources: `3fc520b0fbb7f0cc290906657b40fe288765b6de5c0015f72de9a3a94b9c413f`
+- desk_path: `e0012bf8592ca42548174bd809277f425e4b0329d3a39ce069e55c9369208b50`
+- geometry: `55ab4fcd52d8fea939fe877f0f765e53734ed6bc2e70222cabcfc3dc8bb1dc65`
+
+Manifesto QA `22947d5c47487137b9e37138f29322d99181c7d0cb0bc655dba67fd2e444ae80`; manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Provas específicas precisam corresponder à revisão final e ao alvo real.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Sequência adicional C43/C44 —10/10/2026
+
+Preparação apenas; nenhuma ativação autorizada/executada. Fingerprints correntes: percurso `580e6619937e7acd382415fa446524dd0b5de5162aea3ff51115cdbbf822f67f`, recursos `bfb2eab205de521e746e86097684bc5f93883d7553f23a7bf96ec7c481869cf1`, cartografia `8e042c65d94b810aa03e9b2a9fe5f1bc10269bc1d1631d006fa1058dc2fc46e8`. Provasready anteriores ficam históricas; nenhuma candidata final.
+
+1. Concluir C43/visuais C37/A-B e consumidores; registar reprodução/correção, fixar revisão+manifestos. Renovar backupDB/ficheiros/chaves/originais e restauro numa novaQA guardada, conferindoIDs/relações/hashes/schema. Não forçar contagens históricas 288 tabelas/5 ficheiros.
+2. Disponibilizar código eassets ativos dessa revisão aprovada, configuração reconciliada e cache conferida. Atalhos/arquivo usam `PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`; estáfalse no ativo e só true naQA. **Nenhuma migration nova para C43 ou primeiro draft imobiliário.**020000 já instalada: não repetir. Antes de habilitar, conferir gestor(email verificado+allowlist), rotas e manifesto realmente servido. Rollback: flag false e código/assets compatíveis; preservar drafts/estadoarchived/auditoria.
+3. Recursos: gestor autenticado GET/POST `/management/opportunity-resources-install`somente se 030000 ausente.3 tabelas de associação+1 coluna documents+função/3 triggers; 0 recursos/originais criados automaticamente. ClamD/GD exigidos pelas operações binárias afetadas, sem bloquear rascunho/metadados. Down somente vazio; após uso retirar disponibilidade sem eliminar originais/dados.
+4. Percurso: GET/POST `/management/balcao-install`somente para migrationspendentes 190000; 2 colunas+1 definição imutável, 0 conversões/dossiers/etapas. Disponibilização `INVESTOR_PATH_ENABLED`separada, depois deaceitação/instalação; reversão porflagpreserva 19 etapas/5 fases, IDs/resultados/documentos/consentimentos.
+5. Cartografia: gestor/MFA: prévia/crosswalk/hash→aplicar níveis 1→2→3 sem duplicar. Seativo continuar 0 ecorrespondênciasiguais, previsão 393 limitesinternos=11 províncias+128 distritos+254 postos; 0 territórios novos, 31/157 pendentes. Publicação dascamadasseparada. Reversão 3→2→1 somente novas intactas/não usadas, nem publicadas; guardar originais/hash/crosswalk/receipts e relações.
+6. Contratos especializados: `PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED`ficafalse no ativo. **Não habilitar com este loteAPI parcial.**Completar formulário/bindings/condições finais/DUAT/transação/workflow e provas por versão/perfil; depois planopróprio na mesma auditoria. Desligarflag conservaJSON privado; rollback de código deve manter chave/payloads sem descartá-los. Instalar recursos ou importarcartografia não valida/submete/aprova/publica contrato nem ativa cálculo fiscal.
+
+Plano detalhado anterior conservado abaixo; aplicação documental ativa autenticada, scan próprio dasderivadas e operação permanenteClamD continuam dependências específicas.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Sequência corrente reconciliada — 10/10/2026
+
+Plano preparado para futura autorização; nenhuma ação ativa executada. Revisão não candidata: percurso `daace78d4e0999984dab2561d60778878eb901cd88adeaf539a1a674f88c6767`, cartografia `8e042c65d94b810aa03e9b2a9fe5f1bc10269bc1d1631d006fa1058dc2fc46e8`, recursos `3b576d542bb742afb753958d53647421e9a26d77ee680273c9e85d8a1fad285e`. `ready=true` antigo representa outra preparação e não instalação/conclusão.
+
+| Ordem | Ação futura | Dependência/efeito previsto | Reversão |
+| --- | --- | --- | --- |
+|0|Concluir critérios visuaisA/B, C37 e consumidores; corrigir falhas e fixar commit/assets/fingerprints.|Provas de API/persistência não substituem interface. Não há candidata final agora.|Corrigir/revalidar só critérios afetados; preservar provas anteriores.|
+|1|Renovar backup de DB+ficheiros privados/chaves/originais/metadados e restaurar em nova QA loopback*_test:55441.|Guarda antes da escrita; comparar schema/IDs/relações/hashes/classificações/RLS/ficheiros. 288 tabelas/5 ficheiros são histórico09/10, não contagem a forçar. Provas de reversão/compatibilidade da candidata.|Nunca sobrescrever escritas posteriores sem reconciliação. Restauro ativo permanece fora desta autorização.|
+|2|Disponibilizar código/assets/configuração mantendo INVESTOR_PATH_ENABLED=false e TERRITORY_GEOMETRY_IMPORT_ENABLED=false.|Correções países/documentos/seletores não criam nem reclassificam dados por deploy. ClamD/GD somente nas operações binárias afetadas.|Rollback de código compatível preservando payloads novos/originais. CLI documents:import-batch --apply continua recusado no ativo.|
+|3|Gestor ativo autorizado: GET/POST /management/opportunity-resources-install **somente se030000ausente**.|Prévia/backup/hash/autorização atuais;3 tabelas de associação+1coluna documents+função/3triggers;0 documentos/recursos/geometrias criados automaticamente. Não repetir instalações básicas.|Down somente vazio; após uso preservar dados/originais e desligar disponibilização em vez de apagar.|
+|4|GET/POST /management/balcao-install somente para migrations pendentes, prevista190000.|2 colunas+1 definição imutável;0 conversões/dossiers/etapas automáticas. Prova A/Bvisual atual exigida. 19 etapas/5fases e roteiros legados preservados.|Down recusa após uso; desabilitar flag mantendo definição/dossiers/história.|
+|5|Habilitar INVESTOR_PATH_ENABLED em ação separada, após schema e aceitação.|Mostra percurso;19 etapas somente ao criar dossier novo; ferramentas diretas/URLs/IDs permanecem.|Flagfalse, sem apagar dossier/resultados/documentos/tarefas/consentimentos.|
+|6|Preparar prova específica cartográfica vinculada ao fingerprint/alvo/backuprestaurado/UI; habilitar rota separadamente; gestor/MFA GET /management/territory-geometry-import?level=1 → POST, depois2, depois3.|Cada prévia deve conservar exemplar/hash/scan/crosswalk/pai/conflitos. **Se ativo continuar0 e mesmas correspondências únicas:393=11+128+254 novas internas**,0 geo_locations/locais/perímetros de investimento. 31/157 pendentes de fora. QA 393inclui32novas e361preservadas; replay 0 novas. Scan vencido exige renovar prova por bytes, sem reabrir aceitação oficial.|POST /management/territory-geometry-import/{batch}/reverse com MFA/razão/idempotência; **postos→distritos→províncias**. Recusa descendentes ativos da edição mesmo sem FK, uso/alteração/publicação; só exclusão lógica de novos intactos não usados. Preservar reutilizados/catalogue/hash/histórico.|
+|7|Divulgar camadas por consumidor/âmbito autorizado em ação separada.|Importador não publica. Limites administrativos não são DUAT/perímetro do investimento; não transformar internal em public para passar ensaio. Mecanismo de divulgação de limites administrativos continua a concretizar conforme política existente.|Retirar camada/autorização sem eliminar geometrias/originais/relações.|
+
+Aplicação documental em lote no ativo exige mecanismo autenticado próprio, ainda pendente; o comando existente serve prévia e ensaio isoladoQA. Não adicionar esse lote à sequência ativa como se nomear --actor autenticasse. Schema/workflow especializado preparado não integra estas migrations nem é ativado por elas; sua futura revisão deve ter provas e plano próprios no mesmo backlog.
+
+ClamD real e tipos/derivadas já demonstrados mantêm suas provas; arranque após reboot, assinaturas e PHPativo/GD são critérios específicos em aberto. Importação/publicação não ativa nenhum cálculo fiscal. [Relatório](relatorio-executivo.md) / [backlog](backlog.md).
+
+**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores. 361 e2/39/179 são a baseline 09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.
+
+
## C37 — causa confirmada; seleção de conta QA corrigida — P0, visual pendente
O pedido de reabertura referia a conta esperada18. A captura manual21:22–21:24UTC demonstra que foi selecionada a conta13 restaurada. O MFA foi alcançado, mas a autenticação nunca se completou. Causa concreta: credenciais MFA da conta13 cifradas pela chave de origem, incompatíveis com a chave estávelQA; a conta18 sintética não foi desafiada nessa tentativa. Nenhuma chave, MFA ou conta13 foi alterada para contornar o problema.
diff --git a/docs/investmoz/v2/auditoria-portal/propostas-perfis-modulares-sla.md b/docs/investmoz/v2/auditoria-portal/propostas-perfis-modulares-sla.md
new file mode 100644
index 00000000..e6b6d6ad
--- /dev/null
+++ b/docs/investmoz/v2/auditoria-portal/propostas-perfis-modulares-sla.md
@@ -0,0 +1,80 @@
+# Perfis modulares e SLA — propostas para decisão
+
+10/10/2026. Complemento da matriz existente, sobretudo AUD-OP-04, PROFILE-22/28/31. **Nenhuma proposta abaixo está aprovada, instalada como perfil ativo ou aplicada aos prazos.** Não designa pessoas reais. A criação e recuperação dos quatro rascunhos já existe; submissão e publicação continuam bloqueadas até aprovação do perfil e implementação demonstrada do adaptador correspondente.
+
+## Fundamento e compatibilidade
+
+A Especificação do Formulário de Cadastro de Oportunidades, exemplar SHA256 `9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504`, §25.4, parágrafos extraídos 2101–2105, exige perfil aprovado e imutável por versão submetida, regras declarativas, documentos mínimos e gates aprovados pelo administrador funcional e governance owner. **Não define os campos destas quatro categorias.** Os campos propostos são uma decisão de produto, não uma transcrição de obrigações legais. Os parágrafos 123 e 1801 admitem gestão de SLA/escalamento sem aprovação automática, mas não fixam prazos. O documento de perfis v1 fornece Promotor, Validador, Publicador, Auditor e dupla de superutilizadores; coordenação, parecer e recurso correspondem a responsabilidades desses papéis, já modeladas nas atribuições.
+
+O schema canónico original de 110 definições conserva o seu hash e significado. Reutilizar `module_profile_version`, campos comuns financeiros, países, mercados, riscos, relações, localizações, documentos, evidências e imagens; preservar `owner_user_id`, organização, IDs e revisões atuais. Para atributos sem campo canónico, propor uma extensão versionada do contrato/adaptador, com correspondência explícita às coleções existentes; **não inserir chaves não permitidas no schema atual nem criar tabelas paralelas**. O repositório já usa PostgreSQL/PostGIS e Fortify; estas propostas não dependem de MySQL, Keycloak ou CRM externo.
+
+Rascunho aceita campos incompletos; valida formato dos dados efetivamente preenchidos, preserva valores e aponta erros junto ao campo. Submissão congela perfil, hash dos dados/recursos e documentos aplicáveis. Aprovação e publicação revalidam autorizações, gates e materialidade. Uma mudança do perfil cria outra versão; não muda retroativamente um processo submetido. Seleção territorial não prova titularidade nem geometria de parcela; valor ausente não vira zero.
+
+## Quatro propostas de contrato
+
+| Perfil proposto, ainda inativo | Regra concreta de submissão | Documentos e gates propostos | Fundamento e efeito |
+| --- | --- | --- | --- |
+| `concession-qa-proposal-v1` | Identificar objeto, entidade concedente, representante, regime/procedimento declarado, âmbito territorial ou digital, duração positiva com unidade, modelo de remuneração/obrigações e condições de participação. Se houver terra, usar módulo territorial e indicação das autorizações externas; se houver construção, declarar licenças aplicáveis. Datas de início/fim coerentes; não apresentar concessão ainda pretendida como direito atribuído. | Documento do objeto/procedimento e prova de representação; quando existentes, ato/contrato e título territorial. Gates `technical_review`, `legal_territorial_review`; decisão externa exigida somente quando a matriz de aplicabilidade do perfil a identificar. | §25.4 + campos comuns de promotor, localização, licenças, evidências e milestones. Se a decisão externa não existe, guardar preparação e marcar pendente; nunca fabricar autoridade, prazo ou direito. Publicar chamada/preparação só se o perfil aprovado distinguir claramente esse objeto de uma concessão atribuída. |
+| `financing-qa-proposal-v1` | Identificar projeto/beneficiário e representação; instrumento pretendido, moeda, montante positivo, investimento total, financiamento assegurado, necessidade remanescente, finalidade, calendário de desembolso e cenário financeiro. Soma das rubricas = total; assegurado ≤ total; pedido ≤ necessidade. Se dívida: prazo positivo, periodicidade e condições indicativas; se capital: percentagem e direitos propostos; garantias só quando oferecidas/exigidas. | Estudo/plano financeiro e evidência do financiamento declarado assegurado; documentos da entidade e representação. Gates `technical_review`, `financial_review`, `legal_tax_due_diligence`. | Reutiliza investimento/financiamento, cenários, entidades e documentos existentes. Não calcula aprovação, elegibilidade regulatória ou score de sucesso; financiamento pretendido permanece distinto do assegurado. Condições e percentagens não são inventadas para campos vazios. |
+| `supply-qa-proposal-v1` | Identificar comprador/requisitante, objeto e especificação, quantidade positiva, unidade, destino, calendário e critérios de aceitação. Preço total ou método de cotação explicitamente declarado; se valores preenchidos, moeda única e quantidade × preço reconciliada, distinguindo impostos declarados. Capacidade, licenças ou certificações só são obrigatórias quando o próprio perfil/procedimento as exigir. | Especificação/termos de referência e representação; licenças/certificados aplicáveis e prova de capacidade declarada. Gates `technical_review`, `legal_territorial_review`; financeiro quando pagamento antecipado/garantia for condição declarada. | Reutiliza produtos/inputs, mercados, país, milestones, contratos/licenças e evidências. Pedido de fornecimento não equivale a contrato celebrado. Não presume regime de contratação pública ou taxas fiscais pela categoria. |
+| `other-qa-proposal-v1` | Exigir descrição do subtipo, finalidade, destinatários, resultado esperado, dados/documentos aplicáveis e indicação dos riscos. Promotor não escolhe livremente requisitos/gates para dispensar controlos: coordenação funcional aprova um subtipo e versão antes da submissão. Bloquear uso de “outros” para contornar concessão, terra, financiamento ou negócios existentes. | Documento que define objeto e representação; mínimos e gates declarados no subtipo aprovado. Base `technical_review` + `legal_territorial_review`, dispensas só fundamentadas no perfil aprovado. | §25.4 exige perfil ativo, não uma categoria sem regras. O rascunho livre é recuperável; a publicação aguarda classificação funcional explícita, sem criar um cadastro duplicado. |
+
+Regras comuns propostas: referências documentais pertencem à mesma oportunidade, são recuperáveis e respeitam perfil/organização; ClamD e integridade por hash são necessários para disponibilizar binários. “Documento existente mas decisão externa pendente” difere de “documento obrigatório ausente”. Uma fonte oficial identificada continua aceite, sem segunda validação de autenticidade. A aplicação do seu âmbito e período continua rastreável.
+
+## Correspondência de responsabilidades com papéis existentes
+
+| Responsabilidade | Correspondência existente / proposta | Limite |
+| --- | --- | --- |
+| Coordenação da validação | `validator` + `validation_coordinator`, já permitido nas atribuições | Atribui revisão; não aprova o próprio processo nem substitui pareceres obrigatórios. |
+| Revisão técnica e jurídica | `validator` + `technical_reviewer` / `legal_reviewer`, já permitidos | Cada tarefa requer atribuição, competência e independência; acumular papéis não dispensa impedimentos. |
+| Coordenação editorial | `publisher` + `publication_coordinator`, já permitido | Atribui publicação a Publicador distinto e verifica âmbito; não transforma aprovação interna em decisão externa. |
+| Instância de recurso interno | `validator` + `appeal_reviewer`, já permitido | Exige revisor independente das intervenções anteriores; não é instância de recurso legal externo. |
+| Administrador funcional e governance owner | **Proposta D-M1:** os dois titulares distintos da dupla existente aprovam conjuntamente conteúdo e versão, com MFA e registo dos dois atos | Esta cerimónia de aprovação de perfil ainda não existe. Não criar outro papel ou escolher titulares reais; decisão funcional e disponibilização pública permanecem separadas. |
+| Suporte operacional | Não existe responsabilidade `support` no contrato de atribuições atual. **Proposta:** coordenação da validação assume triagem; apoio do Balcão usa as permissões operacionais já existentes | Suporte não ganha revisão, aprovação, publicação ou acesso universal a documentos. Uma extensão de responsabilidades precisa de decisão explícita e teste. |
+| Auditoria | `auditor`, já existente | Consulta/audita; não instala, aprova ou publica pela acumulação de papéis. |
+
+## Decisões a apreciar, sem bloquear trabalho independente
+
+| Decisão | Regra proposta | Efeito se aprovada / alternativa |
+| --- | --- | --- |
+| D-M1 — Aprovar conteúdo das quatro versões e a correspondência de responsabilidades? | Aprovar a tabela como primeira versão; propor os dois titulares distintos da dupla existente como aprovadores conjuntos, nas funções de administração funcional e governance owner, com MFA, hash e data de cada ato. | Permite implementar a cerimónia de aprovação e ativação versionada, editores e gates. Até lá, os quatro rascunhos continuam recuperáveis e bloqueados para submissão. Não designa pessoas reais nem publica automaticamente. |
+| D-M2 — Concessão antes de decisão externa? | Admitir uma ficha pública de chamada/intenção quando autorizada, rotulada como preparação; uma ficha de direito atribuído exige documento da decisão competente. | Evita confundir promoção com concessão legal. Se só se admitir direito já atribuído, gate externo permanece bloqueante para publicação. |
+| D-M3 — Financiamento e fornecimento com preço/condições indicativos? | Admitir indicadores identificados como propostos, com fonte/cenário/data; não marcar contrato, financiamento assegurado ou compromisso. | Mantém preparação paralela; requer revisão editorial clara. Se se exigirem termos vinculativos, a publicação aguarda esses documentos. |
+| D-M4 — “Outros” genérico? | Exigir subtipo aprovado; nenhum Promotor pode dispensar gates. | Reduz contorno de categorias. Coordenação classifica a preparação sem interromper ferramentas e tarefas independentes. |
+| D-S1 — Entidade sem exercícios completos? | Nova versão explícita admite entidade recém-criada com declaração de inexistência de histórico e cenário/projeções separados; nunca demonstrações fictícias. | Reconciliar mínimo de um exercício do schema atual com regra dos períodos existentes; requer novo contrato/adaptador e teste, não alteração silenciosa do original. |
+| D-S2 — Unidades/urbanismo/materialidade? | Unidades/rooms/floors obrigatórios apenas nos tipos do perfil aprovado; comparar limites urbanísticos apenas com limite declarado e documento/âmbito aplicável. Mudança de título, preço, objeto, direitos, localização, perfil ou evidência relevante exige nova revisão. | Não presume limite oficial ou unidade ausente. A configuração exata por tipo e as tolerâncias de materialidade permanecem uma decisão expressa. |
+| D-R1 — Perda simultânea dos dois titulares? | Preparar cerimónia de recuperação por duas pessoas independentes formalmente designadas, com identidade/MFA recuperados por procedimento existente, motivo, alerta e substituição atómica auditada. Sem designação, não existe bypass de gestor, bootstrap repetido ou terceiro superutilizador. | A substituição normal da dupla já existe. A recuperação simultânea exige política e operadores designados antes de ser habilitada; backup do schema não resolve perda de MFA. |
+
+## SLA operacional proposto — não é prazo legal
+
+Versão proposta `opportunity-sla-proposal-20261010-v1`. **Nenhuma data `due_at` foi preenchida por esta proposta.** Dias úteis são uma configuração a aprovar, com fuso `Africa/Maputo`, calendário e feriados explicitamente registados; não inventar calendário oficial. Relógios por tarefa, não um prazo único que bloqueia todo o percurso.
+
+| Tarefa | Prazo proposto | Responsável funcional | Início, pausa e escalamento propostos |
+| --- | ---: | --- | --- |
+| Triagem e atribuição | 2 dias úteis | Validador com responsabilidade de coordenação | Começa na submissão válida. Escalar à coordenação suplente formalmente designada ao vencer; não escolher automaticamente um Validador. |
+| Revisão técnica | 10 dias úteis | Validador técnico atribuído e independente | Começa na atribuição; pode correr em paralelo com jurídico. Pedido fundamentado de informação pausa somente a tarefa afetada. |
+| Revisão jurídico/territorial | 10 dias úteis | Validador com responsabilidade jurídica/territorial | Mesma regra; decisão externa tem estado e relógio separados, sem prazo externo inventado. |
+| Parecer interno específico | 5 dias úteis | Destinatário explicitamente designado por competência | Começa quando o pedido e evidências estão acessíveis. Parecer não aprova automaticamente o gate. Escalar à coordenação da revisão ao vencer. |
+| Correção pelo Promotor | 15 dias úteis | Promotor autor ou coeditor autorizado da organização | Começa na devolução com lista concreta. Ao vencer, lembrar e permitir pedido de extensão fundamentado; sem rejeição ou arquivo automático. |
+| Revisão de correção | 5 dias úteis | Validador responsável pela revisão afetada | Começa na ressubmissão; gates não afetados podem ser reutilizados só com identidade/hash e regra material demonstrados. |
+| Conferência editorial e publicação | 3 dias úteis | Coordenação editorial atribui; Publicador distinto executa | Começa após aprovação interna e evidências de divulgação. Impedimento documental suspende esta tarefa; não altera aprovação para decisão externa. |
+| Admissibilidade e decisão de recurso interno | 2 + 10 dias úteis | Coordenação de recurso + Validador independente dos autores/revisores/decisores prévios | Relógios separados; motivo e evidências preservados. Sem recurso decidido pelo próprio autor/decisor, mesmo com múltiplos papéis. |
+| Incidente / suspensão de acesso | 1 dia útil para triagem | Coordenação e suporte com responsabilidade expressa; decisão por papel autorizado | Triagem não dá a suporte poder de aprovação. Risco concreto pode justificar suspensão auditada; alerta e próxima ação visíveis. |
+
+Proposta de alerta: um lembrete ao atingir 80% do prazo e escalamento ao vencer; tolerância operacional de 1 dia útil apenas para alerta, sem alterar vencimento nem aprovação. **Sem limite automático de ciclos**: ao terceiro ciclo, revisão pela coordenação da qualidade das exigências, com continuação fundamentada. Ausência de resposta não significa aprovação, rejeição ou arquivamento. Responsabilidade suplente não equivale a pessoa fictícia.
+
+**D-SLA:** aprovar/rever os prazos da tabela, relógios/pausas, lembrete, tolerância, tratamento do terceiro ciclo, calendário e responsabilidades/suplentes. Efeito: preencher `tasks.due_at` somente para novas tarefas ou reprogramação explicitamente auditada; manter tarefas históricas e prazos acordados. Não depende de envio externo de email nem de integração para mostrar fila, vencimento e próxima ação no portal.
+
+## Publicação: significado a usar na interface e relatórios
+
+1. **Aprovação interna:** revisão da versão pelo Validador; não dá visibilidade pública e não substitui decisão de entidade externa.
+2. **Disponibilização com acesso restrito** (antigo rótulo “publicação interna”): ação independente do Publicador, com versão congelada; apenas perfis e organização autorizados podem recuperar a ficha. Não significa acesso por todas as contas autenticadas.
+3. **Publicação no catálogo público:** âmbito `public` aprovado e ação independente do Publicador; projeção pública permitida, preservando documentos, contactos, avaliações e dossier privados. Suspensão/arquivo e classificação de exemplo continuam a impedir a exibição conforme as políticas existentes.
+
+O estado técnico legado `published` é preservado; o texto da interface também apresenta o âmbito efetivo. O âmbito solicitado pelo Promotor difere da disponibilização efetiva. Uma alteração privada em preparação não é apresentada como nova versão pública concluída.
+
+## Implementação incremental e aceitação
+
+Após decisão D-M1–M4: registar versões imutáveis pelo serviço de versões existente, declarar bindings e gates no adaptador sem cadastros paralelos; editores por categoria; testes de campos parciais/422/novas sessões; Promotor → correção → aprovação independente → disponibilização por âmbito; organização alheia e múltiplos papéis negados. Cada nova versão mantém migração/adaptador compatível e reversão por desativação de disponibilização, preservando o snapshot submetido. D-S1/S2 e SLA são decisões independentes.
+
+Instalação de recursos/perfis/percurso permanece **030000 → 040000 → 190000**. Instalar schema não aprova este documento, não atribui perfis, não inicia SLA e não publica geometrias. C37, dashboard Promotor QA21 e cenários A/B exigem interface; nenhuma contagem global de testes os encerra.
diff --git a/docs/investmoz/v2/auditoria-portal/relatorio-executivo.md b/docs/investmoz/v2/auditoria-portal/relatorio-executivo.md
index b6e25862..9aa19e2a 100644
--- a/docs/investmoz/v2/auditoria-portal/relatorio-executivo.md
+++ b/docs/investmoz/v2/auditoria-portal/relatorio-executivo.md
@@ -1,5 +1,239 @@
# InvesteMoz — relatório executivo do lote 3
+
+## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em 2026-10-10T10:32:41+00:00: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **91 pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `profile_restore_20261010_104956_test:55441` → **295 tabelas com linhas/hashes iguais e 69 ficheiros fisicamente recuperados por hash**; todos os ficheiros referenciados recuperados por hash. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+## Contagens atuais por requisito
+
+| Estado | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+|parcial|3229|6379|
+|não implementado|145|446|
+|dependente de decisão concreta|5|5|
+|implementado mas não ativado|1|1|
+|concluído e demonstrado|6|7|
+
+3.386 requisitos verificáveis e 3.386 linhas consolidadas; 6.838 ocorrências de origem. Sem novo fecho integral; provas QA descritas por critério.
+
+
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco conserva a revisão semântica anterior; o estado atual está no início do documento; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+
+## Perfis v1: resultado do lote em QA — 10/10/2026
+
+A v1 foi lida integralmente: 530 parágrafos, confrontados com os 471 do exemplar anterior, AGENTS, auditoria, código, schema PostgreSQL e configuração. Fortify, contas, documentos, relações, IDs, classificações, histórico, cinco fases e 19 etapas foram preservados. Keycloak foi avaliado como recomendação; não há necessidade de SSO/federação demonstrada para substituir Fortify neste lote. A aceitação das fontes oficiais permanece intacta.
+
+**A mesma matriz contém 3.386 requisitos/linhas e 6.838 ocorrências de origem.** Os 3.354 requisitos e 5.830 referências anteriores foram conservados. Acrescentaram-se 32 requisitos verificáveis, os 1.001 parágrafos dos dois exemplares e sete referências diretas da reconciliação. Parágrafos de estrutura e tabelas são referências, não pedidos independentes. Inventário: 591 exemplares, versões e anexos; 202 ficheiros acessíveis nesta varredura, incluindo 12 marcadores de bloqueio Office preservados por bytes/hash.
+
+| Estado canónico | Requisitos | Ocorrências |
+| --- | ---: | ---: |
+| parcial | 3228 | 6371 |
+| não implementado | 146 | 454 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+O sexto concluído é apenas **AUD-PROFILE-27**, a avaliação arquitetural de Keycloak. Não encerra autenticação visual nem uma integração externa. **AUD-OP-03 passa a parcial**, pelas regras e transições novas; o workflow integral continua aberto.
+
+QA: **http://127.0.0.1:18097**, destino efetivamente verificado `desk_restore_20261009_174726_test:55441`, com guarda antes de escrita. Foram preparadas 12 contas sintéticas, com MFA configurado e confirmado normalmente por Fortify, duas organizações e quatro representações. O ensaio comprovou:
+
+- Dashboard do Promotor → links devolvidos pela interface → criação do rascunho 15 → gravação idempotente → nova sessão MFA → recuperação → edição pelo outro Promotor autorizado da mesma organização. Autor e ID permanecem; outra organização, tipo não autorizado e transferência de organização recebem 403.
+- Quatro pedidos de Promotor, comprovativos privados com ClamD real e hash recuperado, acompanhamento noutra sessão e aprovação independente. Rejeição pode registar conferências falsas sem inventar validação. Auditor com outro papel continua sem escrita operacional.
+- Revogação do Validador 24: sessão antiga recebe 401; nova sessão MFA autentica, mas o papel já não autoriza. Inicialização da dupla 27/28 pelo terceiro aprovador 29; substituição atómica 28→30; dupla atual 27/30, terceiro negado, replay negado e sessão anterior invalidada.
+- Recuperação do titular 30 por código Fortify noutra sessão, sem desativar MFA; código consumido não autentica. Desativação de MFA, eliminação e mudança de email do titular são recusadas. Auditor recupera e exporta metadados filtrados, sem snapshots privados.
+- Consumidores territoriais do Promotor corrigidos para rotas autorizadas: 11 províncias, **Cabo Delgado** selecionada, guardada e recuperada com o mesmo ID/nome; uma área geométrica devolvida pela API. O desenho no navegador continua por demonstrar.
+
+**Continuam abertos:** C37, cenários A/B e C43 na interface; contratos especializados completos e vínculos canónicos; submissão/aprovação/publicação positivas, agendamento e versão pública; filas dos coordenadores, pareceres, incidentes de suporte, decisões de recurso, SLA e governança; âmbito provincial de autorização; tokens/dispositivos; privacidade e todas as operações documentais por tipo/perfil. A submissão real do rascunho 15 responde 422 controlado por contrato Create incompleto. Revisão/correção positiva foi ensaiada com uma fixture explicitamente submetida, não com uma submissão real.
+
+API e persistência estão demonstradas nos escopos acima. Interface preparada e compilada; nenhum navegador automatizável foi inventariado, portanto não há aceitação visual. TypeScript, build QA e PHPStan passaram; 14 testes específicos, com 446 asserções, passaram. A contagem não substitui a prova por requisito.
+
+Manifesto QA demonstrado: `22947d5c47487137b9e37138f29322d99181c7d0cb0bc655dba67fd2e444ae80`. Manifesto ativo preservado: `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`. Não há revisão candidata fixada enquanto faltar a aceitação visual.
+
+Acumulação com a permissão administrativa antiga foi reconciliada antes da alteração: uma conta com atribuição v1 não usa a criação legada para contornar organização/tipo; a revogação não restaura automaticamente privilégio antigo mais amplo. Auditor com permissão legada continua sem escrita administrativa. Testes de compatibilidade comprovam as negações; gestores sem atribuições v1 conservam as funções anteriores. Caso C49 adicionado, sem alteração de privilégios ativos.
+
+Preservação por ID/colunas originais comprovada em 18 tabelas, incluindo conta 18, documentos e auditoria; manifesto ativo inalterado. Ativo consultado exclusivamente em transação READ ONLY (`investemoz:5432`): perfis 040000 ausentes e flag desativada; 020000 instalada, 030000/percurso ausentes, zero geometrias. **Nenhuma escrita ou alteração de privilégios ativos.** QA mantém 393 geometrias privadas; faltam 31 distritos e 157 postos, já nomeados. Publicação de camadas é separada.
+
+Evidências sanitizadas: `profiles-v1-http-qa.json`, `profiles-v1-mfa-enrollment-qa.json`, `profiles-v1-recovery-audit-qa.json`, `profiles-v1-current-version-qa.json`, `profiles-v1-preservation-qa.json`, `profiles-v1-reconciliation-proof.json`, `profiles-v1-final-qa.xml` e `profiles-v1-build-qa.log`, em `storage/app/private/investmoz-v2/portal-audit/`. Credenciais, cookies, segredos e códigos não constam dos relatórios.
+
+[Correspondência por requisito](perfis-v1-reconciliacao.md), [roteiro manual](roteiro-manual-perfis-v1.md), [backlog](backlog.md), [ativação e reversão](plano-ativacao.md). Relatório e backlog também disponíveis no servidor QA, com autenticação, em `/qa-auditoria/relatorio-executivo` e `/qa-auditoria/backlog`.
+
+
+
+> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.
+
+
+## Acesso à Gestão de Oportunidades — lote C43/C44, 10/10/2026
+
+QA exclusiva: http://127.0.0.1:18097, alvo real `desk_restore_20261009_174726_test:55441`. Ativo consultado por transação SQL READ ONLY; 0 escritas/instalações/publicações ativas. Cinco fases/19 etapas, 5 dossiers/95 etapas e 393 geometrias QA preservados. C37 e aceitação visual permanecem abertos.
+
+Gestores QA 14/17 têm email verificado+`manage-portal`; gestor 17 possui MFA normal. Investidores QA 13/18 não têm gestão. No ativo, a leitura confirmou contas 2/13 autorizadas, 020000 instalada e 030000 ausente; o dashboard ativo contém título Gestão de Oportunidades e ação antiga Criar oportunidade. Não há hotfile/cache de configuração/cache de rotas a explicar a ausência. URL configurado ativo: http://portal-investidor.test; **URL/conta da sessão reportada ainda desconhecidos**, sem atribuição especulativa de causa a essa conta.
+
+**C43 — causas encontradas no código/compilação:**(1)AppSidebar mostrava só o primeiro filho de cada grupo, descartando oportunidades; (2)menu Painel apontava /investidor mesmo para gestor; (3)dashboard de gestão colocava criação no fim como Criar oportunidade, sem rótulo Nova oportunidade. A secção de gestão só é devolvida pelo backend a contas verificadas em portal.managers; o seu ocultamento para investidor é autorização esperada, não motivo para conceder perfil administrativo.
+
+Correção QA: atalhos Gestão de Oportunidades/Nova oportunidade no início do dashboard, sidebar/menu agrupado; Painel da gestão→/dashboard, dossiers→/investidor. Nova ação archive conserva o rascunho em status archived/deleted_at=null; delete/exclusão lógica mantém o contrato anterior. Restauro volta a draft, ID/histórico intactos, sem publicação. Código usa flags false por omissão; QA usa assets `public/build-qa-opportunities`, versão Inertia desse manifesto. **`public/build` ativo manteve SHA 75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94.** Recursos 030000 não são requisito para navegar/criar rascunho básico.
+
+**C44 — progresso específico:**primeiro adaptador imobiliário aceita campos fornecidos nas 24 propriedades realEstatePatch, validando tipos/enums/limites/UUID e recusando campos desconhecidos/de resposta. Guarda/merge privadamente no management_draft atual. Ainda faltam formulário especializado, vínculos canónicos, condições finais/Create/Response, DUAT/transação e workflow. Nenhuma coleção/tabela paralela, renumeração ou decisão externa criada. O.source.json conserva o retrato histórico da extração, não certifica o estado runtime atual.
+
+- `dashboard-active-readonly.json`: configuração/contas elegíveis/instalação/manifesto ativo, sem boot HTTP/escrita de sessão no ativo.
+- `dashboard-opportunities-http-qa.json`: links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtro archived→restore→GET. Oportunidade QA 13, ID estável/quatro eventos, 12 originais e relações/documentos/dossiers preservados; 6 publicadas mantidas; outra conta 403.
+- `dashboard-manager-mfa-http-qa.json`: gestor 17, MFA em duas sessões→dashboard→gestão→recuperação/reload→logout; 0 alterações de registos. `dashboard-navigation-catalogue-qa.json`: menu Painel da gestão→/dashboard, dossiers privados→/investidor, atalhos únicos e ausência de gestão para investidor.
+- `real-estate-draft-http-qa.json`: outra oportunidade QA 14, rascunho imobiliário parcial no draft existente→nova sessão→patch merge→cinco 422 sem mutação→outsider 403; schema normativo SHA 9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
+- `dashboard-real-estate-qa.xml`: casos nomeados Dashboard OpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest, 8 ensaios/201 asserções. Typecheck, build QA e PHPStan dirigidos passaram; contagem não substitui os critérios visuais.
+- `resource-originals-preservation-http-qa.json`: cinco binários anteriores preservados e novo PDF válido recuperado/parseado, 0 novos recursos. Prova ClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
+- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`: fontes/trechos/IDs/versões preservados, 3354 requisitos/linhas e 5830 ocorrências; 3349 abertos apresentados uma vez cada. Estado AUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.
+
+| Grupo de trabalho dos abertos | Requisitos | O que falta / próxima ação |
+| --- | ---: | --- |
+| Não implementados |145|Workflow integral segregado; rascunhos incompletos procura/capacidade e jornadas educativas ainda por fazer; demais critérios específicos não implementados no relatório por ID. Implementar workflow sobre draft/auditoria após contratos/gates; educação não começa enquanto prioridades abertas.|
+| Parciais |3183|Contrato imobiliário apenas API; DUAT/transações/campos/regras finais e vínculos; cartografia 31 distritos/157 postos/mapas por consumidor; relações/citações; acervo/PDFs/partilhas/derivadas; parâmetros fiscais; negócios/direitos/mandatos; reconciliação documental/UX e ativação. Inclui 4 decisões com estado original, sem bloquear tarefas QA independentes.|
+| Preparados emQA |19|Escopos concretos de rascunhos/recursos/maturidade, países/origem/estatísticas, seletor provincial, Balcão/percurso/CRM/orientação/simulador/parceria/fundiário/importação privada com provasQA. Completar critérios restantes na interface e operações/tipos ainda abertos; ativação permanece separada. Não são 19 requisitos globais concluídos.|
+| Instalados com falha de acesso |2|AUD-DASH-01(C43) e AUD-UI-01(C37/inspeção). Código/backendQA corrigidos nos escopos descritos; identificar sessão reportada e demonstrar dashboard/cliques e loginA/B completos. Confirmar visualmente sem conceder gestão ao investidor.|
+
+**Lista integral legível:**http://127.0.0.1:18097/qa-auditoria/pedidos-abertos, gestorQA 14/17.3349 cartões, um por ID, com pedido, lacuna, próxima ação, critério, fontes/versões/evidências e filtros de grupo/módulo. Vista derivada da [matriz única](matriz-requisitos.csv), sem edição nem estados paralelos; investidor 403. Os grupos são editoriais, distintos dos estados canónicos: 3199 parciais, 145 não implementados, 4 decisões, 1 implementado não ativado, 5 concluídos de âmbito restrito.
+
+Decisões humanas preservadas: pares exatos das 6 oportunidades com âncoras/clusters; identidade/termos/contactos do operador; URLs/serviços/responsáveis institucionais; modelo/indicadores/baseline de sucesso. Não reabrir aceitação das fontes oficiais; não inventar pares, parâmetros ou score.
+
+Visual pendente:[roteiro curto](demonstracao-dashboard-oportunidades.md). API/persistência/assets são provas separadas de interface; nenhum clique automatizado/cenárioA/B visual foi alegado.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Lote independente I0–I3 — 10/10/2026
+
+QA exclusiva: http://127.0.0.1:18097; alvo confirmado `desk_restore_20261009_174726_test:55441`. Testes de feature usam outra QA, `investmoz_test:55441`, com guarda antes de qualquer escrita. Sem alterações, instalação, importação ou publicação na base ativa. Cinco fases/19 etapas preservadas;5 dossiers/95 etapas na QA web, sem criação de jornadas educativas.
+
+| Requisito | Entrega e prova | Critérios ainda abertos |
+| --- | --- | --- |
+| AUD-GEO-01/02/03; C38 | Correspondências explícitas Maputo Província, Maputo Cidade e Matola; descendentes por nome exato+pai. Ação autenticada/MFA no servidor 18097 insere 32 limites internos:2 províncias+8 distritos+22 postos. 361 originais e 1990 geo_locations preservados. 32/32 novos recuperados via endpoint consumidor; público: 0/32. 393/393 contextos por serviço;1920/1920 referências territoriais por API. ProvinceSelect liga o nome guardado ao preview sem reescrever valores. |31 distritos/157 postos por nome; localidades sem polígonos neste exemplar; integração renderizada por consumidor e ato de divulgação separados. |
+| AUD-COUNTRY-01–04/06–07, STATS-01 | Provas renovadas por método/formulário: perfil/empresa/manifestação/público/quatro apoios/carteira/interesse público em negócio/wizard/fundiário/três Balcões/simulador/CRM. Gravação→GET→filtro→agregado quando aplicável; residência/constituição/fiscal/fundos distintos da origem declarada; unknown preservado. |Seleção, recibos, variações condicionais, filtros/tabela e nova sessão na interface. Não contar testes documentais selecionados pela palavra original como requisitos de países. |
+| AUD-LAND-01, PART-01, LIB-01/02, SCAN-01; C39/C40 |404 dos originais cifrados corrigido em fundiário e sala de parceria por VerifiedDocumentBinary comum; novos uploads registam tamanho/autor. PDF/PNG/JPEG com ClamD real, hash, quarentena/perfis/partilha/revogação/adulteração/recuperação. Lote documental QA privado, idempotente, sem substituir identidade conflituosa; actor sem permissão/ambiente ativo recusados. |Renderização PDF/impressão, ações visuais e restantes consumidores/tipos; lote ativo autenticado. Serviço ClamD real demonstrado separado de arranque/manutenção permanente/GD ativo. |
+| AUD-OP-02/SCAN-01; C41/C42 |PDFs sintéticos apenas com cabeçalho não provavam legibilidade: novos testes usam PDF válido de uma página, parseado independentemente. No servidor 18097, novo PDF anexado à oportunidadeQA12→scan real→download→nova sessão→recuperação; outra conta 403. Cinco binários anteriores preservados por SHA; PNG/3WebP recuperados, sem novo scan das derivadas. Credenciais fixas do script removidas; passwords/remember tokens de dois atoresQA auxiliares rodados; MFA/conta 18 preservados. |PDF renderizado e interface documental pendentes. O placeholder anterior permanece conservado como evidência e não certifica abertura de PDF. |
+| AUD-OP-03/04 |Schema normativo §26 preparado e rastreável:110 definições,9 contratos Create/Patch/Response, sem renumerar IDs. |Workflow e validação/gates especializados continuam não implementados; nenhum fecho funcional atribuído ao artefacto. |
+| C37, AUD-UI-01, I1–I3 |Evidências anteriores conservadas, nenhum novo ensaio de login investidor neste lote. |Login/reload/logout/nova sessão e A/B completos na interface continuam pendentes. |
+
+| Nível INE 2019 | Esperado no exemplar | Resolvido QA | Pendente |
+| --- | ---: | ---: | ---: |
+| Província |11|11|0|
+| Distrito |159|128|31|
+| Posto |411|254|157|
+| Total |581|393|188|
+
+Os denominadores da edição 2019 não são os 1920 territórios do cadastro existente. [188 lacunas por nome](correspondencias-cartograficas.md), incluindo Cidade De Maputo agregado e Mandie duplicado no próprio workbook; nenhuma equivalência por código/fuzzy, nem fusão de cadastros. Aceitação das fontes oficiais preservada.
+
+**Mesma matriz, sem requisitos amplos recém-fechados:**3354 requisitos/3354 linhas canónicas;5830 ocorrências de origem. IDs, fontes, trechos, diferenças de versão, critérios e estados conservados.
+
+| Estado | Requisitos/linhas | Ocorrências |
+| --- | ---: | ---: |
+| parcial | 3198 | 5380 |
+| não implementado | 146 | 440 |
+| dependente de decisão concreta | 4 | 4 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 5 | 5 |
+
+Evidências privadas: `geometry-crosswalk-http-qa.json` (aplicação posterior22, além das 2+8 anteriores registadas na auditoria), `geometry-crosswalk-preservation-qa.json` (total 32 novas), `geometry-crosswalk-consumers-http-qa.json` (HTTP 32 novas/0 públicas), `geometry-consumers-path-qa.json` (serviço393), `territory-catalogue-coverage.json` (catálogo1920). Não confundir aplicação parcial inicial interrompida por Mandie com duplicação: as 10 já aplicadas foram reutilizadas na continuação; ambiguidade nominal fica pendente e não bloqueia outras correspondências únicas.
+
+Testes dirigidos: `geometry-crosswalk-qa.xml` (casos de vínculo/pai/exemplar/conflito/replay/reversão), `document-independent-qa.xml` (dois percursos PDF/PNG/JPEG/perfis), `document-batch-independent-qa.xml` (um caso ClamD real; dois de fixture), `countries-independent-qa.xml` e `countries-forms-independent-qa.xml` (métodos identificados na [cobertura](cobertura-percursos-i0-i3.md)). TypeScript/build/PHPStan dos componentes alterados passaram. A guarda de concorrência recusou um arranque paralelo de testes; ficou em `countries-forms-independent-lock-refusal-qa.xml`; o ensaio sequencial posterior passou. Isto é tooling protegido, não falha de formulário.
+
+Complemento documental: `document-types-fixture-qa.json`, `resource-originals-preservation-http-qa.json`, `resource-http-actors-rotation-qa.json` e nova versão de `resources-real-http-qa.json`; versão anterior arquivada antes da atualização. Credenciais novas somente no ficheiro privado local; nenhum cookie/OTP/body exportado. Não alterar os originais anteriores para tornar o ensaio verde.
+
+Código preparado e QA API/persistência demonstradas neste âmbito; interface não demonstrada. `candidate_revision_fixed=false`, `integrated_ui_ab_passed=false`, `activation_ready=false`. [Backlog atual](backlog.md) e [ordem de ativação/reversão](plano-ativacao.md). Não há candidata final nem novo backup final de ativação emitido.
+
+**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores. 361 e2/39/179 são a baseline 09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.
+
+
## C37 — causa confirmada; seleção de conta QA corrigida — P0, visual pendente
O pedido de reabertura referia a conta esperada18. A captura manual21:22–21:24UTC demonstra que foi selecionada a conta13 restaurada. O MFA foi alcançado, mas a autenticação nunca se completou. Causa concreta: credenciais MFA da conta13 cifradas pela chave de origem, incompatíveis com a chave estávelQA; a conta18 sintética não foi desafiada nessa tentativa. Nenhuma chave, MFA ou conta13 foi alterada para contornar o problema.
diff --git a/docs/investmoz/v2/auditoria-portal/roteiro-manual-perfis-v1.md b/docs/investmoz/v2/auditoria-portal/roteiro-manual-perfis-v1.md
new file mode 100644
index 00000000..5a256735
--- /dev/null
+++ b/docs/investmoz/v2/auditoria-portal/roteiro-manual-perfis-v1.md
@@ -0,0 +1,116 @@
+# Ensaio manual de perfis v1 — QA exclusiva
+
+
+## Ensaio visual futuro deste lote — contas QA, sem credenciais
+
+Servidor exclusivo **http://127.0.0.1:18097**. Para a instalação, usar o **Superutilizador sintético QA27** já designado na dupla27/30; obter credenciais eMFA somente no ficheiro privado local. **Promotor QA21 continua a conta do dashboard, não substituí-lo por27. C37/QA18 e A/B continuam pendentes; não é pedida nova tentativa agora.**
+
+1. ComoQA27, login/MFA normal e abrir **http://127.0.0.1:18097/management/profile-install**. Conferir oalvo apresentado `desk_restore_20261009_174726_test:55441`, schema instalado, dependências020/030 presentes, provas atuais e dupla existente. Não executarbootstrap ou escolher titulares novos neste servidor usado.
+2. Atualizar a página, terminar sessão einiciar outra. Esperado:mesmo ledger e dupla,semnova instalação ou atribuição. Os testes de instalação desde schema vazio/reversão pertencem àbaseisolada do runner; não remover o040 do servidorQA emuso para demonstrar o botão.
+3. Quando retomarQA21, dashboard→Minhas oportunidades; #30 apresenta acesso restrito e não catálogo; #33 apresenta catálogo público; #32 apresenta aprovação interna,sempublicação. Os originais/contatos privados não entram na projeção pública.
+4. ComoQA21, abrir **http://127.0.0.1:18097/minhas-oportunidades/36/resources**:consultar PDF,DOCX eXLSX sintéticos. Guardar original, excluir logicamente um recurso, esperar404/downloadindisponível; restaurar einiciar outra sessão para recuperar os mesmosbytes. QA24/25 podemconsultar; organizaçãoQA23 énegada.
+5. Selecione CahoraBassa/Chitima ouCidadeMaxixe no consumidor territorial. Esperado:mesmoIDexistente, geometria administrativa comedição2019, legenda eárea selecionada. Guardar/recuperar seleção; não confundir limite administrativo comparceladeinvestimento. Inspecionar cadaoutroconsumidor no roteiroexistente.
+6. Registar URL,conta/ação/resultado visível eestado recuperado. Omitir Cookie,X-XSRF-TOKEN,password,segredo/códigoMFA. Incorporar falhasàmesma matriz antes defixar candidata.
+
+Documentos fundiários QA21: **http://127.0.0.1:18097/investidor/terra-duat/01a12568-c330-73ec-a1ac-543ac0116a26**. Conferir PDF/PNG/JPEG e país MZ/origem PT; abrir impressão e gerar PDF no navegador. A recuperação do modelo por HTTP não demonstra o PDF final.
+
+Partilha QA21/22: **http://127.0.0.1:18097/parcerias/salas/1**. Os três originais estão privados após o ensaio. QA21 partilha explicitamente um; QA22 recupera noutra sessão. QA21 revoga; QA22 deixa de o listar/obter; QA21 mantém o original. QA14 não participante e QA23 não têm acesso à sala.
+
+Este roteiro não declara os passos executados. Instalação ativa e publicação de camadas permanecem ações futuras separadas.
+
+
+
+## Ensaio visual preparado — permanece pendente conforme pedido
+
+URL QA **http://127.0.0.1:18097/dashboard**. Conta **Promotor QA21**, MFA normal, credenciais/código obtidos apenas localmente. Não incluir cookies, cabeçalhos X-XSRF-TOKEN, segredos ou corpo do código em capturas. C37/conta18 é um ensaio independente e continua pendente.
+
+1. Entrar no dashboard como21. Esperado: **Minhas oportunidades** e **Nova oportunidade**, ambos funcionais, no contexto autorizado. URLlista `/minhas-oportunidades`; criação `/minhas-oportunidades/create`.
+2. Abrir cada ID QA30–39 em `/minhas-oportunidades//view` e, nos estados editáveis, `/edit`. Esperado: estado privado e publicação distintos; núcleo único, categoria correta e permissões aplicadas. #36–39devem continuar drafts.
+3. Criar rascunho incompleto, guardar; logout/nova sessãoMFA e recuperar. Não usar as fichas publicadas para substituir este passo. Esperado: mesmos dados/ID, sem mistura com outrosprojetos/oportunidades. Se ainda não houver localizações/documentos, guardar primeiro e abrir **Recursos**.
+4. Nos recursos `/minhas-oportunidades//resources`, selecionar país e hierarquia; conferir mensagem de território cadastrado, geometria selecionada disponível/ausente e mapa. A parcela declarada em DUAT deve manter geometria própria, sem substituir por limiteadministrativo. Conferir original/prévia antes/depois de recuperar.
+5. Num rascunho de ensaio das seis categorias, introduzir erro semântico e guardar; submeter. Esperado:422, mensagem junto ao campo, valores preservados; depois corrigir e resubmeter. Concessão/financiamento/fornecimento/outros devem informar perfilmodularpendente.
+6. Como24, abrir mesma ficha/fila (`/minhas-oportunidades?queue=review`), atribuir/iniciar→solicitarcorreção→21corrige→nova revisão/gates. Registar motivo e documentos da própria versão. Ensaiar parecer por destinatário29: outra resposta negada e tarefa/parecer recuperados sem gateautoaprovado.
+7. Como25, fila editorial (`?queue=publication`), designar Publicador independente; como29, fila `?queue=assigned`, comparar prévia/hash/teaser e publicar. OutroPublicadornãodesignado deve recebernegação; aprovarprópria/mesmaorganização/múltiplospapéis deve continuar negado. Não atribuirresponsabilidadesreais aos atoresQA.
+8. Depois de publicar, solicitar revisão/materialalteração; esperado: publicação anterior preservada até nova revisão. Fundiário32não pode contornar autorizaçãoexternapendente. Conferir suspensão e recuperação dos motivos/tarefas.
+
+Registar por ação URL/ator/ID/estado/API/persistência/resultado visível; associar a mesma matriz. A/B completos e cincofases/19etapas continuam no roteiro existente, sem renumerar. Não fechar critérios por leitura dos dados ou totaldetestes.
+
+
+
+## Ensaio manual atual — Promotor QA e workflow
+
+**URL inicial exato: http://127.0.0.1:18097/dashboard. Conta: Promotor QA — conta sintética 21.** Se necessário, o login normal é `/login`, com MFA Fortify. Credenciais e códigos permanecem exclusivamente no ficheiro privado local; não os copiar para a conversa. Conferir identificação QA/porta 18097; não usar `portal-investidor.test`.
+
+1. Entrar como Promotor 21, concluir MFA e atualizar dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”, sessão mantida. Um retorno a login entra como reprodução pendente, não como sucesso.
+2. Pelo dashboard, clicar “Nova oportunidade”, escolher organização QA representada e categoria imobiliária; criar e guardar **rascunho incompleto**, incluindo um campo opcional limpo. Esperado: ID, estado rascunho e ausência de bloqueio por campos ainda não preenchidos.
+3. Anotar o ID sem copiar informação privada; logout, nova sessão/MFA, dashboard → “Minhas oportunidades” → mesmo ID. Esperado: recuperação exata, organização/autor preservados. Submeter incompleto deve mostrar campos pendentes e manter o rascunho.
+4. Abrir recursos pelo formulário: MZ → Cabo Delgado → distrito válido → principal; guardar/reabrir. Esperado: mesmos IDs/nome, filhos coerentes; mapa administrativo quando disponível. Não usar limite administrativo como geometria de parcela. Carregar documento sintético permitido; confirmar scan/recuperação e vínculo ao mesmo registo.
+5. Completar núcleo e módulo imobiliário com dados explicitamente sintéticos. O catálogo de ensaio possui sector/subsector/atividade QA; contacto é da organização QA. Usar `sale`, `warehouse`, `completed`, condição `good`, áreas positivas, moeda/preço positivo, ocupação/título/ónus/avaliação e licença aplicável; documento e localização selecionados no contrato. Preencher resumo/pedido/evidências e declaração de verdade. Para este primeiro ciclo usar visibilidade **internal**. Os editores de objetos/grelhas ainda incompletos devem ser registados como falhas: não contornar pela consola nem fingir visual concluída.
+6. Guardar com motivo → submeter. Esperado: `/view`, estado submetido, formulário bloqueado, snapshot/versionamento e tarefa de revisão sem responsável/prazo inventado. A rota `/edit` fechada não deve ser usada para continuar revisão.
+7. Noutra sessão QA entrar como **Validador 24**; abrir o mesmo ID autorizado, atribuir/iniciar revisão, solicitar correção com motivo e campo identificado. Esperado: necessidades de informação, motivo recuperável e tarefa de correção.
+8. Voltar como 21: abrir mesma oportunidade, corrigir, guardar com motivo e resubmeter. Logout/nova sessão deve recuperar a versão corrigida sem perder a decisão anterior.
+9. Como 24: iniciar a revisão dessa versão, registar os gates aplicáveis com decisão/evidência/fundamento; aprovar. Esperado: versão/hash aprovados, aprovação prematura recusada.
+10. Como **Publicador 25**: abrir `/view`, rever prévia, confirmar âmbito e publicar. Esperado: publicado interno, sem exposição na API pública. Para o ensaio público separado, preparar capa, legenda/alt/direitos e duas derivadas analisadas; confirmar prévia/hash e publicar explicitamente.
+11. Como 21, solicitar alteração material com fundamento, editar a proposta privada. Esperado: nova revisão sem aprovação reutilizável; ficha pública anterior permanece intacta. Como 25 suspender com motivo; esperado GET público 404 e história preservada.
+12. Em registo separado, como 24 rejeitar com fundamento; como 21 pedir recurso; como **revisor independente 29** reabrir. Esperado: rejeição original conservada. Rejeitor e membro da organização devem ser recusados. Conta 31 com papéis acumulados/Auditor continua sem escrita. Não atribuir responsabilidades reais às contas sintéticas.
+
+Recolher por passo apenas hora UTC, perfil/ID, URL sem tokens, ação, resultado visível e referência do registo. Omitir Cookie, X-XSRF-TOKEN, passwords, segredo/código MFA e documentos privados de capturas. C37/investidor 18 e cenários A/B continuam no roteiro existente, separados deste ensaio. Sucesso HTTP abaixo não certifica nenhum dos passos visuais.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).
+
+
+**Endereço inicial: http://127.0.0.1:18097/dashboard.** Não usar portal-investidor.test nem outra porta. O servidor verifica `desk_restore_20261009_174726_test:55441` antes de escritas. Em Network, confirmar o header `X-Investmoz-QA-Target` de uma resposta de página/API. Capturas devem omitir Cookie, X-XSRF-TOKEN, Authorization, credenciais, segredos e corpos de login/MFA.
+
+Credenciais e material MFA ficam apenas no ficheiro local privado `storage/app/private/investmoz-v2/portal-audit/profiles-v1-actors-private.json`. Consulte no editor e no autenticador local; não os copie para a conversa. Todas as contas sintéticas foram configuradas normalmente por Fortify sob a chave QA estável. Não gerar outra chave nem desativar MFA.
+
+## Contas e estado atual
+
+| Conta QA | Estado após os ensaios |
+| --- | --- |
+| 20 | Público, sem criação de oportunidades |
+| 21 | Promotor da organização A; autor do rascunho 15 |
+| 22 | Outro Promotor autorizado da organização A; coedição |
+| 23 | Promotor da organização B; acesso à oportunidade 15 negado |
+| 24 | Validador revogado; conta e login MFA preservados |
+| 25 | Publicador; sem edição técnica ou aprovação de rascunho |
+| 26 | Auditor; leitura e exportação de metadados |
+| 27 e 30 | Os dois Superutilizadores atuais |
+| 28 | Titular substituído; conta preservada, administração negada |
+| 29 | Terceiro aprovador do bootstrap QA; não é Superutilizador |
+| 31 | Promotor + Validador + Auditor; restrição de leitura prevalece |
+
+## Primeiro ensaio: Promotor, recuperação e coedição
+
+1. Numa sessão QA isolada, entrar como 21: login → MFA → dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”. Atualizar a página mantém a sessão; registar se volta ao login.
+2. Clicar “Minhas oportunidades” → abrir 15 → editar. Esperado: mesmo ID, organização e rascunho; título editado por 22 e Cabo Delgado recuperados. O dossier privado não se transforma em oportunidade publicada.
+3. Selecionar província/distrito disponíveis e conferir o mapa/estado de cobertura. Guardar com fundamento. Esperado: mensagem de gravação; mudar o pai limpa filhos. Limite administrativo não representa perímetro do terreno.
+4. Logout → nova sessão/login MFA 21 → dashboard → Minhas → 15. Esperado: campo, nome, ID, versão e mapa recuperados. Separar prova do desenho, API e persistência.
+5. Noutra sessão, 22 → dashboard → Minhas → 15 → editar/guardar. Esperado: autorizado; autor 21 preservado e editor 22 registado. Nova sessão 21 recupera a edição.
+6. Como 23, abrir o URL da oportunidade 15. Esperado: 403 controlado sem conteúdo da organização A. Como 31, leitura permitida e gravação negada; os dados não mudam. Como 20, criação não aparece e acesso direto é negado.
+7. Como 21, solicitar arquivo com razão. Esperado: pedido persistido, estado draft mantido. Promotor não ganha exclusão/restauro. Submissão e publicação completas continuam indisponíveis pelo contrato; não interpretar isso como falha MFA/C37.
+
+## Pedido de Promotor e decisão independente
+
+1. Como 20: dashboard → “Solicitar perfil de Promotor” → `/perfil/promotor`. Esperado: somente pedidos e comprovativos próprios. Se necessário, preparar um anexo sintético privado no dossier do Balcão; aguardar scan clean real.
+2. Escolher representação, organização existente autorizada quando aplicável, tipos, comprovativo e fundamento. Submeter. Esperado: ID e estado pending; nenhuma criação autorizada antes da decisão.
+3. Logout/nova sessão 20 → acompanhamento. Esperado: mesmo pedido recuperado. Antes de repetir por erro de interface, conferir o acompanhamento; a mesma chave não duplica o pedido.
+4. Noutra sessão, 27 ou 30 → Gestão de perfis → consultar comprovativo → conferir identidade, representação e documentos → escolher tipos → decidir com razão. Declarar apenas conferências efetivamente realizadas. Rejeição pode manter conferências falsas e não concede perfil. Aprovação própria é negada.
+5. Nova sessão 20 após aprovação → dashboard. Esperado: Minhas/Nova para o âmbito e tipos aprovados; outro tipo/organização continua negado. Documentos e decisão original permanecem.
+
+## Revisão, auditoria e operações críticas
+
+1. Como 25, consultar 15. Esperado: sem edição técnica, aprovação ou publicação de draft. A publicação positiva integral ainda depende do contrato completo; não fabricar estados para encerrar o teste.
+2. Como 26 → Auditoria → filtrar `superuser_replaced` → exportar JSON. Esperado: metadados da substituição 28→30, sem segredos ou snapshots privados; exportação auditada. Escrita operacional continua negada com outros papéis.
+3. Como 27/30 → Gestão de perfis. Esperado: dupla 27/30, alertas, pedidos, atribuições e formulários. Como 28, administração negada; como 24, login MFA válido mas papel revogado.
+4. Para ensaio positivo do Validador, atribuir explicitamente 24 pelo 27/30, com tipos e fundamento. Preservar a revogação anterior. Filas e completude ainda pendentes. Ao terminar, revogar a nova atribuição: sessão antiga perde acesso; nova sessão conserva autenticação, sem o papel.
+5. Para uma substituição adicional, usar candidato sintético QA com MFA. Preparar → outro titular aprova → aplicar. Esperado: sempre dois titulares, terceiro isolado negado, replay negado e acesso anterior revogado. Não escolher titulares reais nem repetir bootstrap para regressar a 28.
+6. Elevação exige outro titular, ação/objeto exatos, papel operacional e MFA recente. Não remove impedimentos de autoria/Auditor. Após 15 minutos, decisão administrativa exige novo MFA por logout/login QA; não desativar MFA.
+7. Recuperação do titular usa código Fortify local, sem captura. Código consumido não autentica. Emergência quando ambos perdem todos os meios permanece uma decisão/procedimento institucional.
+
+## Registar os resultados na mesma matriz
+
+Por ação: conta QA, URL, hora UTC, ID, esperado, observado, mensagem visível, status API e campo após nova sessão. Omitir segredos. Associar ao AUD-PROFILE correspondente; falhas adicionais entram nos casos de reprodução. C37 e A/B não são fechados por este roteiro.
+
+Os cenários A/B mantêm as cinco fases e 19 etapas do roteiro existente: criação → gravação → nova sessão → recuperação → aplicabilidade → ferramenta → resultado no dossier → Balcão → acompanhamento, incluindo tarefa independente em paralelo e ausência de mistura/acesso indevido.
+
+Relatório e backlog autenticados: http://127.0.0.1:18097/qa-auditoria/relatorio-executivo e http://127.0.0.1:18097/qa-auditoria/backlog. Lista da matriz: `/qa-auditoria/pedidos-abertos`. Acesso do gestor QA 17, Auditor 26 ou Super 27/30 com MFA; Público e Promotor isolado não recebem acesso administrativo.
diff --git a/docs/investmoz/v2/auditoria-portal/workflow-oportunidades-qa.md b/docs/investmoz/v2/auditoria-portal/workflow-oportunidades-qa.md
new file mode 100644
index 00000000..a3dc669c
--- /dev/null
+++ b/docs/investmoz/v2/auditoria-portal/workflow-oportunidades-qa.md
@@ -0,0 +1,263 @@
+# InvestMoz — contratos e workflow de oportunidades em QA
+
+
+## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em 2026-10-10T10:32:41+00:00: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **91 pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `profile_restore_20261010_104956_test:55441` → **295 tabelas com linhas/hashes iguais e 69 ficheiros fisicamente recuperados por hash**; todos os ficheiros referenciados recuperados por hash. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+
+
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco conserva a revisão semântica anterior; o estado atual está no início do documento; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+## Próximo trabalho executável e decisões separadas — lote semântico atual
+
+| Prioridade / requisito | O que já tem prova QA | Falta / próxima ação e critério concreto |
+| --- | --- | --- |
+| P0 — UI-01/C37 | Diagnóstico/MFA preservados; ensaios HTTP21 não fecham18. | C37 e confirmação visual continuam pendentes conforme pedido. Quando retomados, dashboard→MFA→sessão→refresh→logout→novo login; rastreio sanitizado e primeiro ponto de perda. Nenhum novo teste visual solicitado agora. |
+| P1 — OP-04 / PROFILE-28/25 | Seis editores/regras no contrato do servidor; dez drafts e doze rejeições por campo recuperadas. | Observar cada categoria na UI21, erro junto ao controlo e nova sessão; reconciliar unidades aplicáveis, entidade/título/cadastro e limites urbanísticos com gates; completar Response/§27 apenas reutilizando entidades. Não regredir source/enums/IDs ou tornar campos incompletos obrigatórios para guardar. |
+| P1 — OP-03 / PROFILE-11/12/19 | Filas, parecer atribuído, resposta, revisão e coordenação editorial com task/hash/papéis; negações específicas. | Interface por24/25/29, reatribuição e revogação; incidentes, disponibilidade e revisão periódica. Parecer externo requer responsabilidade institucional concreta, não um ator fictício; aprovação interna não substitui decisão externa. |
+| P1 — GEO-03 / COUNTRY/STATS | Seis contratos ligam localização/documentos por IDs e país MZ; investimento recupera mercadoFR; editores consultam geometrias no nível selecionado. | Verificar visual de todos os consumidores afetados, país/origem→recuperação→filtro→estatística por formulário. Resolver nomes pendentes do pacote:31distritos+157postos; localidades/parcelas não inferidas de limites administrativos. Reutilizar importação autenticada/idempotente; publicação de camada é separada. |
+| P1 — OP-02 / LIB / PROFILE-23 | Originais por perfil, negação de organização23, cifragem/hash, PNG e duas derivadas ClamD; PDF do ensaio atual separado. | Continuar DOCX/XLSX, partilhas, PDFs/exportações/derivadas sem prova específica; preservar originals/versões. Consistência de erro404 recurso excluído versus423 scan pendente foi corrigida no consumidor de oportunidades. |
+| P1 — PROFILE-23 | Dois avisos preexistentes de league/commonmark identificados no lote anterior. | Avaliar consumidores e corrigir compatibilidade emQA; não apagar o achado nem atribuir a Opis. |
+| P2 — PROFILE-31 / OPS-01 | 190000confirmadaQA/ausenteativo;030/040QA;baseBalcãoativa instalada, hashes atualizados. | Construir instalação/bootstrap autenticados040 com duasidentidades reais explicitamente designadas; não mudar titulares nem retirar privilégio ativo automaticamente. Apósvisual, fixar candidata e renovarbackup/restauro dessa revisão; executar apenas migrações faltantes pelo mecanismo adequado. |
+
+Decisões independentes, sem bloquear este lote:
+
+1. **Concessão, financiamento, fornecimento e outros:** quais versões imutáveis de perfil modular, campos obrigatórios, documentos e gates são aprovadas para cada categoria? Sem esse contrato, guardar/editar funciona; submissão/revisão/publicação continuam bloqueadas.
+2. **SLA:** qual política versionada fixa prazo por tipo de tarefa, tolerância, número de ciclos e escalamento? Quem assume formalmente cada competência de coordenação, parecer técnico/jurídico, publicação e recurso? Manter prazo nulo e atribuição explícita até existir decisão; não usar nomes/prazos de QA como norma.
+3. **Condições sem regra inequívoca:** qual âmbito/citação estabelece a aplicabilidade de unidades/limites urbanísticos e materialidade? Como reconciliar o mínimo de um exercício do schema com entidades sem exercícios existentes? Não substituir valores ausentes por zero nem alterar silenciosamente a versão aceita.
+
+Não iniciar jornadas educativas novas. Mantêm-se cinco fases/19 etapas e URLs, dossier privado, oportunidade publicada, fontes oficiais aceites e histórico.
+
+
+## Ativação reconciliada: 030000, 040000 e **09/190000** — nenhuma execução no ativo
+
+A omissão de **2026_10_09_190000_prepare_investor_path** na sequência anterior foi um erro documental; a extensão **continua necessária e não foi substituída**. Não confundir com **2026_10_07_190000_create_internal_virtual_desk**, que já está instalada no ativo.
+
+| Recurso | QA restaurada:55441 | Ativo investemoz:5432, READ ONLY | Evidência |
+| --- | --- | --- | --- |
+| Gestão020000 | Instalada | Instalada | Ledger/schema anteriores preservados |
+| Balcão07/190000 e orientação08/120000 | Instalados | Ambos no ledger | Leitura efetiva das migrações, sem boot de sessão ativa |
+| Recursos09/030000 | Instalada | Ausente | Tabelas e ledger; não repetirQA |
+| Perfis10/040000 | Instalada | Ausente | Tabelas/verificaçãoQA; nunca instalada no ativo neste trabalho |
+| Percurso09/190000 | **Ledger + duas colunas + definição publicada** | **Ledger ausente; duas colunas ausentes; nenhuma definição** | `dashboard-active-readonly.json`, `opportunity-semantic-environment-qa.json` |
+
+DefiniçãoQA `61000919-0000-4000-8000-000000000001`, publicada, SHA256 **e0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf**. Duas colunas: `investor_journeys.path_definition_id` e `journey_steps.path_detail`. Mantém cinco fases e rastreabilidade das19etapas; não renumera/reescreve os roteiros existentes. Recurso preparado/definição publicada não demonstra A/B na interface.
+
+Dependências verificadas no código: **030000** usa oportunidades/documentos existentes e cria três coleções de recursos; **040000** acrescenta quatro tabelas de autorização/auditoria, uma coluna de revisão em users e três colunas em opportunities, preservando identidades/histórico; não usa as colunas de190000. **190000** usa investor_journeys/journey_steps/questionnaire_versions e depende da baseBalcão/orientação incluída no instalador. Não existe dependência DDL entre030/040 e190; disponibilizar o workflow requer020+030+040 e tasks/catalogue existentes; disponibilizar o percurso integrado requer190 e as capacidades instaladas/configuradas. Os fingerprints incluem código comum de perfis: alterar o código invalida provas antigas de readiness, sem converter isso numa dependência de schema.
+
+| Ordem futura | Ação concreta e efeito / contagem esperada | Dependência e reversão |
+| --- | --- | --- |
+| 0 | Incorporar visualC37/Promotor21/A-B; corrigir falhas e fixar revisão/manifesta/configuração. Renovar dumpDB+ficheirosoriginaisprivados+chaveestável e restauroverificado numa novaQA. | Candidata ainda não fixada; provas antigas não são backup dessa revisão. Nunca key:generate indiscriminado. |
+| 1 | Disponibilizar código/Composer/bundle após aprovação de ativação, flagsfalse. | Nesta análise só buildQA foi atualizado; manifestativo preservado. Reversão para código/build anteriores e flagsfalse; assegurar compatibilidade de leitura. |
+| 2 | **030000**, se ledger/schema realmente ausentes: préviaGET e aplicaçãoPOST autenticada `/management/opportunity-resources-install` com hash/confirm. | Três coleções resource e metadado de cifra; **zero documentos/dados publicados/importados**. Base020/documentos existentes. Downgrade destructive recusado se originais cifrados usados. |
+| 3 | **040000**, se ausente: instalar quatro tabelas/colunas através de mecanismo autenticado e bootstrap/recuperação da dupla, ainda por implementar paraativo. | Não substituir por migrateglobal/configmanual para contornar guarda. **Zero contas/grants QA** noativo. Titulares/reconciliação de permissões reais precisam de decisão explícita. Código independente de190. |
+| 4 | **09/190000**, se ausente: préviaGET e aplicaçãoPOST autenticada `/management/balcao-install`; instalador seleciona só migrações faltantes. | BaseBalcão07/190000 e orientação08/120000 jáconstamdoativo: não repetir. **Duas colunas + uma definição publicada**, se não existir equivalente; **zero dossiers/journeys criados automaticamente**. Versões publicadas imutáveis. |
+| 5 | Configurar catálogos/responsabilidades reais e instalar apenas contratos modulares aprovados; comparar IDs/citações/versões. | A autoridade sintética QA3e1ff315… e atores21–31 não são dados deativação. Sem alteração automática de valores legados. |
+| 6 | Importação cartográfica autenticada privada `/management/territory-geometry-import`: prévia/correspondências/hash→aplicação idempotente→auditoria. | QA393=11províncias+128distritos+254postos; ativo0naúltimaleitura. **393 candidatas inequívocas**, sujeitas à prévia da revisão e aos mesmos IDs;188pendentes(31/157), sem criar geometrias falsas. Contagem final deve ser medida no alvo. Reversão por lote/metadados e histórico, sem apagar cadastros. |
+| 7 | Ativar flags de perfis/oportunidades e percurso separadamente, testar navegação completa e permissões. | 030/040 antesdoscontratos/workflow;190antesdodisponibilizarpercurso; C37/visual/A-B não encerrados. Preparação paralela e acesso direto continuam. |
+| 8 | **Publicar camadas, oportunidades ou documentos como ações separadas e explícitas**. | Nenhuma instalação/importação publica automaticamente; publicação não ativa cálculo fiscal. Usar decisões/evidências/hash atuais e autorização de divulgação. |
+
+Reversão: desativarflags/voltarbundle compatível e conservar originais/auditoria. Migrações usadas não devem ser eliminadas por rollback genérico;190recusadownquandohápercurso,030recusacomcifrados,040preservaperfil/oportunidade. Quando necessária reversão de dados, usar o restauroverificado da candidata com reconciliação das escritas posteriores. **ready=true é preparação; não instalação, ativação nem aceitação funcional.**
+
+
+## Reprodução e evidências adicionais — mesmo inventário
+
+| Caso / requisito | Passos e esperado | Observado / causa | Correção e estado |
+| --- | --- | --- | --- |
+| C55 — OP-02 | QA21→PDF limpo→exclusão lógica→GETdownload. Esperado: recurso indisponível, sem atribuir falha de scan. Restaurar e recuperar original. | HTTP423/quarentena porque download juntava row inexistente à condição de scan. | Separa ausência/exclusão404 de quarentena423; teste específico e ensaioPDFweb18097. Originais/hash preservados; visualpendente. Prova da falha `opportunity-semantic-documents-http-qa-attempt1.json`. |
+| C56 — OP-04/PROFILE-25 | Promotor21 abre editor de categoria; campos de núcleo devem ter um único valor/controlo e erros associados. | Revisão do código: formulário legado e contrato canónico duplicavam título/território/campos, com valores independentes. | Contrato canónico único no modo perfil; formulário legado continua na gestão própria. BuildQA/TS e payloadAPI; observação visualpendente. |
+| C57 — OP-04/PROFILE-28 | Guardar fim anterior ao início/ciclo/serviços incompletos/documento estrangeiro/comunidade sem consulta/financeiros incompletos; recuperar noutra sessão; submeter. | Regras anteriores aceitavam objetos opacos sem semântica suficiente. | 12negativas422 com caminho de campo; rascunhos recuperados; seis cenários completos submetidos/revistos. Não extrapolar a regras jurídicas ainda sem âmbito/gate. |
+| C58 — OP-03/PROFILE-19/12 | Parecer com destinatário técnico/jurídico; responder outro ator; aprovar pendente. Depois atribuir publicação e tentar outro Publicador. | Fluxo anterior não tinha destinatário/resposta/fila completa nem atribuição editorial. | #30destinatário29/resposta/tarefa;outro403/aprovação422; #33filaeditorial29/outro25publica403/designado29publica. Sem gateautoaprovado/prazofictício; visualpendente. |
+| 190000 — OPS-01/PROFILE-31 | Comparar ledger/duascolunas/definição QA eativo, distinguir migraçãoBalcão07 depercurso09. | Plano anterior omitia recurso ainda ausenteativo. | 09/190000confirmadaQA e ausenteativo, necessária/nãosubstituída; seqüência autenticada recolocada. Nenhuma execuçãoativa. |
+
+
+## Ensaio visual preparado — permanece pendente conforme pedido
+
+URL QA **http://127.0.0.1:18097/dashboard**. Conta **Promotor QA21**, MFA normal, credenciais/código obtidos apenas localmente. Não incluir cookies, cabeçalhos X-XSRF-TOKEN, segredos ou corpo do código em capturas. C37/conta18 é um ensaio independente e continua pendente.
+
+1. Entrar no dashboard como21. Esperado: **Minhas oportunidades** e **Nova oportunidade**, ambos funcionais, no contexto autorizado. URLlista `/minhas-oportunidades`; criação `/minhas-oportunidades/create`.
+2. Abrir cada ID QA30–39 em `/minhas-oportunidades//view` e, nos estados editáveis, `/edit`. Esperado: estado privado e publicação distintos; núcleo único, categoria correta e permissões aplicadas. #36–39devem continuar drafts.
+3. Criar rascunho incompleto, guardar; logout/nova sessãoMFA e recuperar. Não usar as fichas publicadas para substituir este passo. Esperado: mesmos dados/ID, sem mistura com outrosprojetos/oportunidades. Se ainda não houver localizações/documentos, guardar primeiro e abrir **Recursos**.
+4. Nos recursos `/minhas-oportunidades//resources`, selecionar país e hierarquia; conferir mensagem de território cadastrado, geometria selecionada disponível/ausente e mapa. A parcela declarada em DUAT deve manter geometria própria, sem substituir por limiteadministrativo. Conferir original/prévia antes/depois de recuperar.
+5. Num rascunho de ensaio das seis categorias, introduzir erro semântico e guardar; submeter. Esperado:422, mensagem junto ao campo, valores preservados; depois corrigir e resubmeter. Concessão/financiamento/fornecimento/outros devem informar perfilmodularpendente.
+6. Como24, abrir mesma ficha/fila (`/minhas-oportunidades?queue=review`), atribuir/iniciar→solicitarcorreção→21corrige→nova revisão/gates. Registar motivo e documentos da própria versão. Ensaiar parecer por destinatário29: outra resposta negada e tarefa/parecer recuperados sem gateautoaprovado.
+7. Como25, fila editorial (`?queue=publication`), designar Publicador independente; como29, fila `?queue=assigned`, comparar prévia/hash/teaser e publicar. OutroPublicadornãodesignado deve recebernegação; aprovarprópria/mesmaorganização/múltiplospapéis deve continuar negado. Não atribuirresponsabilidadesreais aos atoresQA.
+8. Depois de publicar, solicitar revisão/materialalteração; esperado: publicação anterior preservada até nova revisão. Fundiário32não pode contornar autorizaçãoexternapendente. Conferir suspensão e recuperação dos motivos/tarefas.
+
+Registar por ação URL/ator/ID/estado/API/persistência/resultado visível; associar a mesma matriz. A/B completos e cincofases/19etapas continuam no roteiro existente, sem renumerar. Não fechar critérios por leitura dos dados ou totaldetestes.
+
+
+Atualizado em **2026-10-10T08:52:56+00:00**. Incremento da mesma auditoria e matriz; não cria inventário paralelo. Este relatório discrimina **código preparado**, **HTTP/persistência demonstrados em QA** e **funcionalidade ativa**.
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+
+## Provas reproduzíveis e limites
+
+| Prova privada local (sem credenciais) | Percurso / camada |
+| --- | --- |
+| `opportunity-workflow-http-qa.json` | 288 pedidos ao servidor 18097, Fortify/MFA normal; dez categorias, gravação/recuperação noutra sessão, ciclo investimento18, correção/gates/aprovação/publicação interna; rejeição/negativas iniciais. |
+| `opportunity-workflow-extended-http-qa.json` | 91 pedidos; recurso29, imobiliário19 público com ClamD/derivadas, confirmação/hash, proposta privada preserva público, suspensão404; fundiário20 autorizado internamente mas publicação422. |
+| `opportunity-workflow-multirole-http-qa.json` | 45 pedidos; autor Prom+Val+Pub403, aprovador Val+Pub403, Auditor acumulado403, três atribuições temporárias revogadas; nova sessão Promotor21 normal. |
+| `opportunity-workflow-territory-tasks-http-qa.json` | 95 pedidos; oportunidade28 localiza principal em segundo lugar, conclui revisão por correção, resubmete sem atribuição herdada e suspende sem tarefas abertas; oportunidade29 conclui tarefa com rejeição. |
+| `opportunity-workflow-verification-qa.json` | Releitura atual do contrato e referências: seis passam, quatro sem perfil; país/localização e hashes documentais. O total territorial inclui fixture QA isolada e não prova cobertura real. |
+| `opportunity-workflow-final-tests-qa.xml` | 19 testes / 426 asserções, zero erros/falhas; testes específicos de estados, binding estrangeiro, integridade de bytes, draft/null, filtros privados e independência. Fixtures de política não são prova de ClamD real. |
+| `profiles-v1-preservation-qa.json` | Registos anteriores de 18 conjuntos conservados por ID/colunas originais; MFA18 e build ativo preservados. Captura 2026-10-10T08:51:35+00:00. |
+
+PHPStan dos componentes alterados, TypeScript e compilação QA passaram. Manifesto QA **`984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8`**; ativo **`75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`**. Nenhuma página foi renderizada/clicada no navegador deste ensaio. A extensão de fonte `source.json` mantém flags false como fotografia histórica da extração, não como configuração do runtime atual.
+
+## Compatibilidade e contratos restantes
+
+Fonte integral: especificação do cadastro, SHA256 `9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504`; §25 campos/semântica, §26 schema, §27 gates. Artefacto normativo de 110 definições preservado, SHA256 `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`. O adapter distingue entrada parcial e submissão, liga documentos/localizações/imagens pelos IDs existentes e valida relações/scan/bytes. Snapshots, decisões, motivos e hashes usam `management_draft`, `workflow_context` e auditoria existentes.
+
+IDs bigint de oportunidades/sectors não foram convertidos aos UUID de exemplos; não foram criados cadastros paralelos. Tarefas reutilizam `tasks`; a sua coluna `opportunity_id` aponta a oportunidades CRM UUID e não recebe o bigint do portal: a relação é explícita por source_system/external_id/correlation_id. Contactos e subsector/atividade reutilizam `contacts`, `investors`, `investor_contacts`, `economic_activities` e versões existentes. As referências acrescentadas para o ensaio são marcadas QA-synthetic, não oficiais, e não devem ser importadas no ativo.
+
+Este incremento **não implementa integralmente** os objetos normativos descritos apenas como object, as relações SQL adicionais do §27 nem o Response integral. Validação estrutural aceita parte desses objetos sem detalhamento: exige continuação semântica antes de ativar os contratos. Aprovação interna é uma decisão identificada de QA; não confirma atos externos, autenticidade ou situação jurídica. DUAT pendente foi recusado na publicação mesmo após todos os gates internos.
+
+O rascunho admite ausência, vazio e null nos campos ainda não preenchidos, preservando as restrições de valores fornecidos e impedindo campos readonly/verified do cliente. Contratos de concessão/financiamento/fornecimento/outros ficam em rascunho até existir perfil versionado aprovado e imutável; não foi fabricada configuração para os submeter.
+
+## Ensaio manual atual — Promotor QA e workflow
+
+**URL inicial exato: http://127.0.0.1:18097/dashboard. Conta: Promotor QA — conta sintética 21.** Se necessário, o login normal é `/login`, com MFA Fortify. Credenciais e códigos permanecem exclusivamente no ficheiro privado local; não os copiar para a conversa. Conferir identificação QA/porta 18097; não usar `portal-investidor.test`.
+
+1. Entrar como Promotor 21, concluir MFA e atualizar dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”, sessão mantida. Um retorno a login entra como reprodução pendente, não como sucesso.
+2. Pelo dashboard, clicar “Nova oportunidade”, escolher organização QA representada e categoria imobiliária; criar e guardar **rascunho incompleto**, incluindo um campo opcional limpo. Esperado: ID, estado rascunho e ausência de bloqueio por campos ainda não preenchidos.
+3. Anotar o ID sem copiar informação privada; logout, nova sessão/MFA, dashboard → “Minhas oportunidades” → mesmo ID. Esperado: recuperação exata, organização/autor preservados. Submeter incompleto deve mostrar campos pendentes e manter o rascunho.
+4. Abrir recursos pelo formulário: MZ → Cabo Delgado → distrito válido → principal; guardar/reabrir. Esperado: mesmos IDs/nome, filhos coerentes; mapa administrativo quando disponível. Não usar limite administrativo como geometria de parcela. Carregar documento sintético permitido; confirmar scan/recuperação e vínculo ao mesmo registo.
+5. Completar núcleo e módulo imobiliário com dados explicitamente sintéticos. O catálogo de ensaio possui sector/subsector/atividade QA; contacto é da organização QA. Usar `sale`, `warehouse`, `completed`, condição `good`, áreas positivas, moeda/preço positivo, ocupação/título/ónus/avaliação e licença aplicável; documento e localização selecionados no contrato. Preencher resumo/pedido/evidências e declaração de verdade. Para este primeiro ciclo usar visibilidade **internal**. Os editores de objetos/grelhas ainda incompletos devem ser registados como falhas: não contornar pela consola nem fingir visual concluída.
+6. Guardar com motivo → submeter. Esperado: `/view`, estado submetido, formulário bloqueado, snapshot/versionamento e tarefa de revisão sem responsável/prazo inventado. A rota `/edit` fechada não deve ser usada para continuar revisão.
+7. Noutra sessão QA entrar como **Validador 24**; abrir o mesmo ID autorizado, atribuir/iniciar revisão, solicitar correção com motivo e campo identificado. Esperado: necessidades de informação, motivo recuperável e tarefa de correção.
+8. Voltar como 21: abrir mesma oportunidade, corrigir, guardar com motivo e resubmeter. Logout/nova sessão deve recuperar a versão corrigida sem perder a decisão anterior.
+9. Como 24: iniciar a revisão dessa versão, registar os gates aplicáveis com decisão/evidência/fundamento; aprovar. Esperado: versão/hash aprovados, aprovação prematura recusada.
+10. Como **Publicador 25**: abrir `/view`, rever prévia, confirmar âmbito e publicar. Esperado: publicado interno, sem exposição na API pública. Para o ensaio público separado, preparar capa, legenda/alt/direitos e duas derivadas analisadas; confirmar prévia/hash e publicar explicitamente.
+11. Como 21, solicitar alteração material com fundamento, editar a proposta privada. Esperado: nova revisão sem aprovação reutilizável; ficha pública anterior permanece intacta. Como 25 suspender com motivo; esperado GET público 404 e história preservada.
+12. Em registo separado, como 24 rejeitar com fundamento; como 21 pedir recurso; como **revisor independente 29** reabrir. Esperado: rejeição original conservada. Rejeitor e membro da organização devem ser recusados. Conta 31 com papéis acumulados/Auditor continua sem escrita. Não atribuir responsabilidades reais às contas sintéticas.
+
+Recolher por passo apenas hora UTC, perfil/ID, URL sem tokens, ação, resultado visível e referência do registo. Omitir Cookie, X-XSRF-TOKEN, passwords, segredo/código MFA e documentos privados de capturas. C37/investidor 18 e cenários A/B continuam no roteiro existente, separados deste ensaio. Sucesso HTTP abaixo não certifica nenhum dos passos visuais.
+
+
+## Próximo trabalho executável — incremento de 10/10/2026
+
+| Prioridade / requisito | Correção concreta seguinte | Critério de fecho e dependência |
+| --- | --- | --- |
+| P0 — UI-01/C37; DASH-01/C43 | Incorporar ensaio visual com Promotor 21 e, separadamente, investidor 18; registar falhas com URL, ação, estado e resposta sanitizada. | Login/MFA → dashboard → guardar → logout → nova sessão → recuperar, sem loop, perda ou acesso indevido; não substituível por HTTP. |
+| P1 — OP-04; PROFILE-28 | Completar editores e validações semânticas §25: grelhas de serviços/ónus, avaliação/documento, ocupação/título/cadastro, comunidades/consulta/benfeitorias, financeiros/beneficiário efetivo, NDA, governação e franquia; completar Response. Reutilizar contrato e entidades atuais. | Rascunho parcial recuperável; cada condição aplicável recusa dados inválidos e aceita dados/evidências completos; interface por categoria. Confirmar correspondências de objetos opacos do schema, sem alterar os significados legados silenciosamente. |
+| P1 — OP-03; PROFILE-11/12/19/21 | Completar filas/revisões e editoriais, reatribuição, pareceres, incidentes e recurso; manter hash da versão e independência. | Atores distintos e responsáveis explicitamente designados, motivos/evidência e histórico; revogação reavaliada. Ciclo principal já demonstrado por HTTP, não repetir o inventário. |
+| P1 — COUNTRY/STATS/GEO | Completar cobertura por formulário/consumidor, mapas e nomes cartográficos pendentes. | País/origem persistidos → recuperação → filtros/estatísticas; território cadastrado ≠ geometria ≠ mapa apresentado. 393 limites privados não encerram integração visual; faltam 31 distritos e 157 postos. |
+| P1 — OP-02/LIB/PROFILE-23 | Verificar tipos/partilhas/PDFs e derivadas ainda sem prova específica e autorizações do original. | ClamD real separado por operação; hashes/originais preservados; acesso permitido/negado e resultado visível. PNG/documentos do ciclo e duas derivadas já demonstrados. |
+| P1 — PROFILE-23 (achado adicional) | Composer audit apontou dois avisos preexistentes em `league/commonmark`: GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8. Identificar consumidores/configuração e preparar correção compatível em QA. | Prova local `workflow-composer-audit.json`; avaliar aplicação dos avisos e validar os consumidores afetados. Não atribuir aos três pacotes Opis nem declarar exploração demonstrada. |
+| P2 — PROFILE-22/31 | Configuração SLA versionada, instalaçao autenticada de perfis/dupla e preparação de ativação. | Decisões reais explícitas; ensaio backup/restauro da candidata posterior à visual; nenhum prazo ou titular real escolhido por QA. |
+
+**Decisões concretas:** (1) quais versões imutáveis de perfil, campos, documentos e gates são aprovadas para concessão, financiamento, fornecimento e outros? (2) qual política versionada fixa prazos, tolerância, ciclos e escalamento? (3) quem assume formalmente as responsabilidades institucionais e os exatamente dois superutilizadores ativos? Não bloqueiam as correções independentes, nem foram inferidas dos atores sintéticos.
+
+| Grupo dos pedidos abertos (projeção da mesma matriz) | Requisitos |
+| --- | ---: |
+| Parciais | 3187 |
+| Não implementados | 145 |
+| Preparados em QA | 46 |
+| Instalados com falha de acesso | 2 |
+
+Lista integral: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**, sob MFA de gestor/Auditor/Superutilizador QA. Cada cartão conserva o estado canónico, fontes, lacuna e próxima ação. “Preparado em QA” indica um escopo provado, não conclusão total.
+
+
+## Sequência reconciliada de disponibilização futura — não executada
+
+Leitura ativa de 10/10: PostgreSQL `investemoz:5432`, transação READ ONLY, seis oportunidades publicadas; 020000 instalada, 030000/040000/percurso ausentes, flags desativadas, zero geometrias. Build ativo preservado. A revisão candidata **não está fixada**; `ready=true` e fingerprints anteriores não autorizam nem demonstram instalação.
+
+| Ordem | Ação e efeito previsto | Dependência / reversão |
+| --- | --- | --- |
+| 0 | Incorporar visual C37/C43/A/B e workflow, corrigir falhas; fixar revisão, configuração e manifestos. Renovar backup DB + ficheiros privados/originais + chave estável e provar restauro numa nova QA isolada. | Provas anteriores preservadas, sem as apresentar como restauro desta revisão. Não gerar nova chave. |
+| 1 | Disponibilizar código e dependências compatíveis, flags desligadas. Composer adiciona `opis/json-schema 2.4.1`, `opis/string 2.1.0`, `opis/uri 1.1.0`; zero atualizações/remoções preexistentes. | Não importar contas, classificações, contactos ou documentos sintéticos QA. Reverter código/assets compatíveis, preservando payloads/histórico. |
+| 2 | Não repetir 020000. Se 030000 continuar ausente, usar prévia/aplicação autenticada `/management/opportunity-resources-install`: três tabelas, uma coluna documental, uma função e três triggers previstos. | Backup/restauro confirmado; hashes/contagens verificados no estado real; não publica nem habilita o percurso. |
+| 3 | Preparar e testar o mecanismo autenticado 040000: quatro tabelas, uma coluna de utilizador, três de oportunidade, uma função e dois triggers previstos; dupla inicial/substituição independente. | Aplicação atual demonstrada exclusivamente QA. Instalação/bootstrap ativo autenticado ainda pendente; titulares reais não definidos. Não remover privilégios ativos automaticamente. |
+| 4 | Configurar referências/contactos/hierarquia, perfis/tipos/representação, responsabilidades e MFA; quatro contratos modulares apenas após aprovação da versão. | Reutilizar dados mestres reais. As referências sintéticas de ensaio não resolvem cadastros ativos vazios. SLA permanece indeterminado até política aprovada. |
+| 5 | Importação cartográfica autenticada, privada e idempotente; se ativo permanecer zero e correspondências iguais, até **393 = 11 províncias + 128 distritos + 254 postos**. Esperados 581 = 11/159/411; pendentes 188 = 0/31/157, nomes no relatório de correspondências. | Prévia → correspondências inequívocas → scan/hash → aplicar → auditoria; nenhuma localização/conta/perímetro de projeto inventado. Reversão pelo lote preserva origem/uso/histórico. **Publicação de camadas é ação separada.** |
+| 6 | Disponibilizar flags/assets/navegação aprovados e o percurso I1–I3 pela instalação existente, sem repetir ações já presentes. Publicar cada oportunidade separadamente, com aprovação/hash/prévia/âmbito. | Cinco fases/19 etapas preservadas, dossier privado separado. Voltar flags a false limita disponibilização; manter guardas de confidencialidade para novos dados. Não executar down destrutivo após uso. |
+
+Após uso, reverter por configuração compatível, suspensão/arquivo autorizado ou compensação auditada; não eliminar decisões, documentos, consentimentos, relações ou originais. Restauro global exige reconciliar alterações posteriores ao backup. Este plano não contém aprovação de ativação nem declaração de instalação ativa.
+
diff --git a/docs/investmoz/v2/gestao-oportunidades-dashboard.md b/docs/investmoz/v2/gestao-oportunidades-dashboard.md
index 28ab3e69..1aa4f29b 100644
--- a/docs/investmoz/v2/gestao-oportunidades-dashboard.md
+++ b/docs/investmoz/v2/gestao-oportunidades-dashboard.md
@@ -1,5 +1,166 @@
# Gestão de Oportunidades integrada no Dashboard
+
+## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em 2026-10-10T10:32:41+00:00: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **91 pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](auditoria-portal/propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `profile_restore_20261010_104956_test:55441` → **295 tabelas com linhas/hashes iguais e 69 ficheiros fisicamente recuperados por hash**; todos os ficheiros referenciados recuperados por hash. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+
+
+
+## Ensaio visual preparado — permanece pendente conforme pedido
+
+URL QA **http://127.0.0.1:18097/dashboard**. Conta **Promotor QA21**, MFA normal, credenciais/código obtidos apenas localmente. Não incluir cookies, cabeçalhos X-XSRF-TOKEN, segredos ou corpo do código em capturas. C37/conta18 é um ensaio independente e continua pendente.
+
+1. Entrar no dashboard como21. Esperado: **Minhas oportunidades** e **Nova oportunidade**, ambos funcionais, no contexto autorizado. URLlista `/minhas-oportunidades`; criação `/minhas-oportunidades/create`.
+2. Abrir cada ID QA30–39 em `/minhas-oportunidades//view` e, nos estados editáveis, `/edit`. Esperado: estado privado e publicação distintos; núcleo único, categoria correta e permissões aplicadas. #36–39devem continuar drafts.
+3. Criar rascunho incompleto, guardar; logout/nova sessãoMFA e recuperar. Não usar as fichas publicadas para substituir este passo. Esperado: mesmos dados/ID, sem mistura com outrosprojetos/oportunidades. Se ainda não houver localizações/documentos, guardar primeiro e abrir **Recursos**.
+4. Nos recursos `/minhas-oportunidades//resources`, selecionar país e hierarquia; conferir mensagem de território cadastrado, geometria selecionada disponível/ausente e mapa. A parcela declarada em DUAT deve manter geometria própria, sem substituir por limiteadministrativo. Conferir original/prévia antes/depois de recuperar.
+5. Num rascunho de ensaio das seis categorias, introduzir erro semântico e guardar; submeter. Esperado:422, mensagem junto ao campo, valores preservados; depois corrigir e resubmeter. Concessão/financiamento/fornecimento/outros devem informar perfilmodularpendente.
+6. Como24, abrir mesma ficha/fila (`/minhas-oportunidades?queue=review`), atribuir/iniciar→solicitarcorreção→21corrige→nova revisão/gates. Registar motivo e documentos da própria versão. Ensaiar parecer por destinatário29: outra resposta negada e tarefa/parecer recuperados sem gateautoaprovado.
+7. Como25, fila editorial (`?queue=publication`), designar Publicador independente; como29, fila `?queue=assigned`, comparar prévia/hash/teaser e publicar. OutroPublicadornãodesignado deve recebernegação; aprovarprópria/mesmaorganização/múltiplospapéis deve continuar negado. Não atribuirresponsabilidadesreais aos atoresQA.
+8. Depois de publicar, solicitar revisão/materialalteração; esperado: publicação anterior preservada até nova revisão. Fundiário32não pode contornar autorizaçãoexternapendente. Conferir suspensão e recuperação dos motivos/tarefas.
+
+Registar por ação URL/ator/ID/estado/API/persistência/resultado visível; associar a mesma matriz. A/B completos e cincofases/19etapas continuam no roteiro existente, sem renumerar. Não fechar critérios por leitura dos dados ou totaldetestes.
+
+
+## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco conserva a revisão semântica anterior; o estado atual está no início do documento; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+| Investimento — #30 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Imobiliário — #31 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Fundiário/DUAT — #32 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Bloqueada: autorização externa pendente |
+| Venda de negócio — #33 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Pública, só teaser; prova editorial posterior |
+| Parceria de negócio — #34 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Franquia — #35 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | Aceite | Gates e aprovação interna | Interna; sem exposição pública |
+| Concessão — #36 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Financiamento — #37 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Fornecimento — #38 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+| Outros — #39 | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | 422: perfil modular por aprovar | Não elegível | Bloqueada |
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`.
+
+**Falhas corrigidas com prova:** 12 recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Manifesto QA `0e610cd650d6b788edfdc9cbf697d125cb9330958914e13a8a8bbd14a781b395`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluÃdo e demonstrado | 6 | 7 |
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+
+
+
+## Ensaio manual atual — Promotor QA e workflow
+
+**URL inicial exato: http://127.0.0.1:18097/dashboard. Conta: Promotor QA — conta sintética 21.** Se necessário, o login normal é `/login`, com MFA Fortify. Credenciais e códigos permanecem exclusivamente no ficheiro privado local; não os copiar para a conversa. Conferir identificação QA/porta 18097; não usar `portal-investidor.test`.
+
+1. Entrar como Promotor 21, concluir MFA e atualizar dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”, sessão mantida. Um retorno a login entra como reprodução pendente, não como sucesso.
+2. Pelo dashboard, clicar “Nova oportunidade”, escolher organização QA representada e categoria imobiliária; criar e guardar **rascunho incompleto**, incluindo um campo opcional limpo. Esperado: ID, estado rascunho e ausência de bloqueio por campos ainda não preenchidos.
+3. Anotar o ID sem copiar informação privada; logout, nova sessão/MFA, dashboard → “Minhas oportunidades” → mesmo ID. Esperado: recuperação exata, organização/autor preservados. Submeter incompleto deve mostrar campos pendentes e manter o rascunho.
+4. Abrir recursos pelo formulário: MZ → Cabo Delgado → distrito válido → principal; guardar/reabrir. Esperado: mesmos IDs/nome, filhos coerentes; mapa administrativo quando disponível. Não usar limite administrativo como geometria de parcela. Carregar documento sintético permitido; confirmar scan/recuperação e vínculo ao mesmo registo.
+5. Completar núcleo e módulo imobiliário com dados explicitamente sintéticos. O catálogo de ensaio possui sector/subsector/atividade QA; contacto é da organização QA. Usar `sale`, `warehouse`, `completed`, condição `good`, áreas positivas, moeda/preço positivo, ocupação/título/ónus/avaliação e licença aplicável; documento e localização selecionados no contrato. Preencher resumo/pedido/evidências e declaração de verdade. Para este primeiro ciclo usar visibilidade **internal**. Os editores de objetos/grelhas ainda incompletos devem ser registados como falhas: não contornar pela consola nem fingir visual concluída.
+6. Guardar com motivo → submeter. Esperado: `/view`, estado submetido, formulário bloqueado, snapshot/versionamento e tarefa de revisão sem responsável/prazo inventado. A rota `/edit` fechada não deve ser usada para continuar revisão.
+7. Noutra sessão QA entrar como **Validador 24**; abrir o mesmo ID autorizado, atribuir/iniciar revisão, solicitar correção com motivo e campo identificado. Esperado: necessidades de informação, motivo recuperável e tarefa de correção.
+8. Voltar como 21: abrir mesma oportunidade, corrigir, guardar com motivo e resubmeter. Logout/nova sessão deve recuperar a versão corrigida sem perder a decisão anterior.
+9. Como 24: iniciar a revisão dessa versão, registar os gates aplicáveis com decisão/evidência/fundamento; aprovar. Esperado: versão/hash aprovados, aprovação prematura recusada.
+10. Como **Publicador 25**: abrir `/view`, rever prévia, confirmar âmbito e publicar. Esperado: publicado interno, sem exposição na API pública. Para o ensaio público separado, preparar capa, legenda/alt/direitos e duas derivadas analisadas; confirmar prévia/hash e publicar explicitamente.
+11. Como 21, solicitar alteração material com fundamento, editar a proposta privada. Esperado: nova revisão sem aprovação reutilizável; ficha pública anterior permanece intacta. Como 25 suspender com motivo; esperado GET público 404 e história preservada.
+12. Em registo separado, como 24 rejeitar com fundamento; como 21 pedir recurso; como **revisor independente 29** reabrir. Esperado: rejeição original conservada. Rejeitor e membro da organização devem ser recusados. Conta 31 com papéis acumulados/Auditor continua sem escrita. Não atribuir responsabilidades reais às contas sintéticas.
+
+Recolher por passo apenas hora UTC, perfil/ID, URL sem tokens, ação, resultado visível e referência do registo. Omitir Cookie, X-XSRF-TOKEN, passwords, segredo/código MFA e documentos privados de capturas. C37/investidor 18 e cenários A/B continuam no roteiro existente, separados deste ensaio. Sucesso HTTP abaixo não certifica nenhum dos passos visuais.
+
+
+## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](auditoria-portal/workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](auditoria-portal/matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+| parcial | 3229 | 6379 |
+| não implementado | 145 | 446 |
+| dependente de decisão concreta | 5 | 5 |
+| implementado mas não ativado | 1 | 1 |
+| concluído e demonstrado | 6 | 7 |
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+
+**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](auditoria-portal/workflow-oportunidades-qa.md).
+
+
+
+## Estado corrente: acesso ao dashboard C43 —10/10/2026
+
+**C43 — causas encontradas no código/compilação:**(1)AppSidebar mostrava só o primeiro filho de cada grupo, descartando oportunidades; (2)menu Painel apontava /investidor mesmo para gestor; (3)dashboard de gestão colocava criação no fim como Criar oportunidade, sem rótulo Nova oportunidade. A secção de gestão só é devolvida pelo backend a contas verificadas em portal.managers; o seu ocultamento para investidor é autorização esperada, não motivo para conceder perfil administrativo.
+
+Correção QA: atalhos Gestão de Oportunidades/Nova oportunidade no início do dashboard, sidebar/menu agrupado; Painel da gestão→/dashboard, dossiers→/investidor. Nova ação archive conserva o rascunho em status archived/deleted_at=null; delete/exclusão lógica mantém o contrato anterior. Restauro volta a draft, ID/histórico intactos, sem publicação. Código usa flags false por omissão; QA usa assets `public/build-qa-opportunities`, versão Inertia desse manifesto. **`public/build` ativo manteve SHA 75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94.** Recursos 030000 não são requisito para navegar/criar rascunho básico.
+
+**C44 — progresso específico:**primeiro adaptador imobiliário aceita campos fornecidos nas 24 propriedades realEstatePatch, validando tipos/enums/limites/UUID e recusando campos desconhecidos/de resposta. Guarda/merge privadamente no management_draft atual. Ainda faltam formulário especializado, vínculos canónicos, condições finais/Create/Response, DUAT/transação e workflow. Nenhuma coleção/tabela paralela, renumeração ou decisão externa criada. O.source.json conserva o retrato histórico da extração, não certifica o estado runtime atual.
+
+QA exclusiva: http://127.0.0.1:18097, alvo real `desk_restore_20261009_174726_test:55441`. Ativo consultado por transação SQL READ ONLY; 0 escritas/instalações/publicações ativas. Cinco fases/19 etapas, 5 dossiers/95 etapas e 393 geometrias QA preservados. C37 e aceitação visual permanecem abertos.
+
+Gestores QA 14/17 têm email verificado+`manage-portal`; gestor 17 possui MFA normal. Investidores QA 13/18 não têm gestão. No ativo, a leitura confirmou contas 2/13 autorizadas, 020000 instalada e 030000 ausente; o dashboard ativo contém título Gestão de Oportunidades e ação antiga Criar oportunidade. Não há hotfile/cache de configuração/cache de rotas a explicar a ausência. URL configurado ativo: http://portal-investidor.test; **URL/conta da sessão reportada ainda desconhecidos**, sem atribuição especulativa de causa a essa conta.
+
+[Ensaio desde o dashboard](auditoria-portal/demonstracao-dashboard-oportunidades.md),[matriz única](auditoria-portal/matriz-requisitos.csv),[pedidos abertos/backlog](auditoria-portal/backlog.md),[evidências](auditoria-portal/relatorio-executivo.md). API/persistência/assetsQA demonstrados; visual e ativação pendentes.393 geometrias e schema 110 defs não encerram o cadastro funcional.
+
+**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.
+
+
+
+## Estado corrente — 10/10/2026
+
+[Estado corrente na matriz existente](auditoria-portal/matriz-requisitos.csv), [relatório](auditoria-portal/relatorio-executivo.md) e [backlog](auditoria-portal/backlog.md):3354 requisitos/5830origens;32 geometrias adicionaisQA,393 privadas no total; correspondências11/128/254 e lacunas0/31/157. Recuperação documental cifrada fundiário/parceria e loteQA demonstrados por operações específicas; países/origem renovados por formulário. Schema especializado110defs/9 contratos preparado com fonte/hash, ainda sem validaçãoruntime/workflow integrado. Maturidade7/8 no draft foi corrigida em lote posterior ao texto histórico abaixo, sem reinterpretar seis valores legados; isso não conclui publicação/workflow. C37 e A/Bvisuais continuam pendentes. Recursos ativos não instalados no último retrato conhecido, a reconfirmar antes de futura ação; ready/hashes antigos não representam a revisão atual. Nenhuma alteração ativa. Cinco fases/19 etapas e URLs/IDs/cadastros preservados.
+
+As atualizações datadas09/10e entregas abaixo permanecem como histórico, incluindo falhas/contagens posteriormente corrigidas; prevalecem os critérios/evidências atuais do relatório e da mesma matriz.
+
+
Continuação da auditoria — 09/10/2026, após 18:22 locais: [relatório atual](auditoria-portal/relatorio-executivo.md), [mesma matriz consolidada](auditoria-portal/matriz-requisitos.csv) e [backlog atual](auditoria-portal/backlog.md). 3.354 requisitos canónicos / 5.830 linhas de origem; critérios/versões/aliases e percurso interface–API–gravação–recuperação–resultado conservados. QA: 373/376 testes, 4.608 asserções, três ClamD reais saltados. Países públicos/simulador, origem/estatísticas e hierarquia do Balcão demonstrados no servidor; UI e cobertura transversal pendentes. Maturidade 7/8 e draft incompleto educativo reproduzidos como 422 na QA, não concluídos. Recursos não instalados; prova renovada às 16:18:09 UTC, fingerprint `c328f542…`, preview `ready=true`. As provas anteriores abaixo são históricas. Nenhuma escrita ativa por esta auditoria.
Atualização de auditoria — 09/10/2026, 17:23:42 locais: [relatório transversal](auditoria-portal/relatorio-executivo.md), [matriz única](auditoria-portal/matriz-requisitos.csv), [backlog](auditoria-portal/backlog.md) e [plano consolidado](auditoria-portal/plano-ativacao.md). O plano de recursos foi renovado para o hash `e90ab685dac9441b7fc5f9da231770cb607a91b7e991876ded652827d76efa50` e está pronto por leitura, **não instalado**. Backup/restauro verificado em 15:16:03 UTC, validade de 24 h. QA global: 368 passaram/4.401 asserções e três ClamD saltados. UI desta versão pendente por ausência de browser conectado. Os registos de hashes/validade abaixo mantêm-se como histórico, não como prova corrente.
diff --git a/resources/data/investmoz-opportunity-modular.schema.json b/resources/data/investmoz-opportunity-modular.schema.json
new file mode 100644
index 00000000..b76706ce
--- /dev/null
+++ b/resources/data/investmoz-opportunity-modular.schema.json
@@ -0,0 +1,12571 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "$id": "https://investmoz.tempo.co.mz/schemas/opportunity-modular.json",
+ "title": "InvestMozOpportunity",
+ "$defs": {
+ "localizedPublication": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "language_code": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "summary": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "opportunity_id",
+ "language_code",
+ "title",
+ "summary",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "location": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "province_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "district_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "administrative_post_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "locality_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "geometry": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "GeoJSON Geometry in EPSG:4326"
+ },
+ "area_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "sqm",
+ "ha",
+ null
+ ]
+ },
+ "allocation_percentage": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "maximum": 100
+ },
+ "address": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 30
+ },
+ "role_other": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 150
+ },
+ "is_primary": {
+ "type": "boolean"
+ },
+ "active": {
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "required": [
+ "province_id",
+ "district_id",
+ "role",
+ "is_primary"
+ ]
+ },
+ "product": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "quantity": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "name",
+ "category"
+ ]
+ },
+ "asset": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "asset_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "value": {
+ "type": "number",
+ "minimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "name",
+ "asset_type"
+ ]
+ },
+ "employment": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "employment_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "direct_jobs": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "indirect_jobs": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "female_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ },
+ "youth_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "employment_type",
+ "direct_jobs"
+ ]
+ },
+ "impact": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "impact_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "minLength": 1
+ },
+ "indicator": {
+ "type": "string",
+ "minLength": 1
+ },
+ "target": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "impact_type",
+ "description"
+ ]
+ },
+ "moneyItem": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ },
+ "year": {
+ "type": "integer",
+ "minimum": 1900
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "label",
+ "amount",
+ "currency"
+ ]
+ },
+ "evidence": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "evidence_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "document_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "verified": {
+ "type": "boolean"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "evidence_type",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "document": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "mime_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "confidential": {
+ "type": "boolean"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "original_name": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "category",
+ "original_name",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "image": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "alt_text": {
+ "type": "string",
+ "minLength": 1
+ },
+ "is_cover": {
+ "type": "boolean"
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "url",
+ "alt_text",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "realEstate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "transaction_type": {
+ "enum": [
+ "sale",
+ "lease",
+ "investment",
+ "development",
+ "partnership"
+ ]
+ },
+ "property_type": {
+ "enum": [
+ "house",
+ "apartment",
+ "office",
+ "retail",
+ "warehouse",
+ "hospitality",
+ "industrial",
+ "mixed_use",
+ "development",
+ "other"
+ ]
+ },
+ "construction_status": {
+ "enum": [
+ "planned",
+ "under_construction",
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ },
+ "property_condition": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "new",
+ "good",
+ "fair",
+ "poor",
+ "derelict",
+ null
+ ]
+ },
+ "land_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "built_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "enum": [
+ "sqm",
+ "ha"
+ ]
+ },
+ "units": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "rooms": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "floors": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "amenities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "utilities": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "occupancy_status": {
+ "enum": [
+ "vacant",
+ "owner_occupied",
+ "tenant_occupied",
+ "partially_occupied"
+ ]
+ },
+ "title_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "registration_number": {
+ "type": "string",
+ "minLength": 1
+ },
+ "encumbrances": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "price": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent_periodicity": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "monthly",
+ "quarterly",
+ "semiannual",
+ "annual",
+ "other",
+ null
+ ]
+ },
+ "deposit": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "viewing": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "planning_permit_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "use_license_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "transaction_type",
+ "property_type",
+ "construction_status",
+ "land_area",
+ "built_area",
+ "area_unit",
+ "utilities",
+ "occupancy_status",
+ "title_type",
+ "registration_number",
+ "encumbrances",
+ "valuation"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "sale"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "price"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "lease"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "rent",
+ "rent_periodicity"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "construction_status": {
+ "enum": [
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ }
+ },
+ "required": [
+ "construction_status"
+ ]
+ },
+ "then": {
+ "required": [
+ "property_condition"
+ ]
+ }
+ }
+ ]
+ },
+ "landRights": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "operation_type": {
+ "enum": [
+ "investment_with_duat",
+ "transfer_of_improvements",
+ "assignment_subject_to_authorization",
+ "lease_of_improvements",
+ "operating_partnership",
+ "other_legal"
+ ]
+ },
+ "duat_status": {
+ "enum": [
+ "none",
+ "application",
+ "provisional",
+ "definitive",
+ "occupancy_recognition",
+ "community_right"
+ ]
+ },
+ "duat_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "holder_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "holder_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "issuing_authority_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "issue_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "expiry_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "authorized_purpose": {
+ "type": "string",
+ "minLength": 1
+ },
+ "exploitation_plan_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "parcels": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/parcel"
+ }
+ },
+ "improvements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/improvement"
+ }
+ },
+ "communities": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/community"
+ }
+ },
+ "community_consultation": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "overlaps_conflicts": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "required_authorizations": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "consideration": {
+ "type": [
+ "object",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "operation_type",
+ "duat_status",
+ "holder_name",
+ "authorized_purpose",
+ "parcels",
+ "overlaps_conflicts",
+ "required_authorizations"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "duat_status": {
+ "enum": [
+ "provisional",
+ "definitive"
+ ]
+ }
+ },
+ "required": [
+ "duat_status"
+ ]
+ },
+ "then": {
+ "required": [
+ "duat_number",
+ "issuing_authority_id"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "operation_type": {
+ "enum": [
+ "transfer_of_improvements",
+ "lease_of_improvements"
+ ]
+ }
+ },
+ "required": [
+ "operation_type"
+ ]
+ },
+ "then": {
+ "properties": {
+ "improvements": {
+ "minItems": 1
+ }
+ },
+ "required": [
+ "improvements",
+ "consideration"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "operation_type": {
+ "const": "operating_partnership"
+ }
+ },
+ "required": [
+ "operation_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "consideration"
+ ]
+ }
+ }
+ ]
+ },
+ "businessTransaction": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "partnership",
+ "joint_venture",
+ "franchise",
+ "succession",
+ "financing"
+ ]
+ },
+ "legal_entity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "legal_form": {
+ "type": "string",
+ "minLength": 1
+ },
+ "percentage_offered": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "maximum": 100
+ },
+ "asking_price": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "financial_periods": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "assets_liabilities": {
+ "type": "object"
+ },
+ "employees": {
+ "type": "object"
+ },
+ "contracts_licenses": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "litigation_contingencies": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "reason_for_transaction": {
+ "type": "string",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "partner_contribution": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "governance_rights": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "franchise_terms": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "confidentiality_level": {
+ "enum": [
+ "teaser",
+ "nda_required",
+ "restricted"
+ ]
+ },
+ "due_diligence_status": {
+ "enum": [
+ "not_started",
+ "data_room_ready",
+ "in_progress",
+ "completed",
+ "exceptions"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type",
+ "legal_entity_id",
+ "legal_form",
+ "asking_price",
+ "valuation",
+ "financial_periods",
+ "assets_liabilities",
+ "employees",
+ "contracts_licenses",
+ "litigation_contingencies",
+ "reason_for_transaction",
+ "confidentiality_level",
+ "due_diligence_status"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "full_sale"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "properties": {
+ "percentage_offered": {
+ "const": 100
+ }
+ },
+ "required": [
+ "percentage_offered",
+ "governance_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partial_sale",
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "percentage_offered",
+ "governance_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "partner_contribution"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "franchise_terms"
+ ]
+ }
+ }
+ ]
+ },
+ "item": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "product"
+ },
+ "payload": {
+ "$ref": "#/$defs/product"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "asset"
+ },
+ "payload": {
+ "$ref": "#/$defs/asset"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "input"
+ },
+ "payload": {
+ "$ref": "#/$defs/input"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "market"
+ },
+ "payload": {
+ "$ref": "#/$defs/market"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "impact"
+ },
+ "payload": {
+ "$ref": "#/$defs/impact"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "investment"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "financing"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "milestone"
+ },
+ "payload": {
+ "$ref": "#/$defs/milestone"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "license"
+ },
+ "payload": {
+ "$ref": "#/$defs/license"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "risk"
+ },
+ "payload": {
+ "$ref": "#/$defs/risk"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "relation"
+ },
+ "payload": {
+ "$ref": "#/$defs/relation"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "employment"
+ },
+ "payload": {
+ "$ref": "#/$defs/employment"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "environmental_social"
+ },
+ "payload": {
+ "$ref": "#/$defs/environmentalSocial"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ }
+ ]
+ },
+ "parcel": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "cadastral_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "location_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "geometry": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "MultiPolygon"
+ },
+ "coordinates": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type",
+ "coordinates"
+ ]
+ },
+ "overlap_status": {
+ "type": "string",
+ "maxLength": 30
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "location_id",
+ "area",
+ "geometry",
+ "overlap_status",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "improvement": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "improvement_type": {
+ "type": "string",
+ "maxLength": 60
+ },
+ "owner_name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "assessed_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "valuation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "image_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "improvement_type",
+ "owner_name",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "community": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "consultation_status": {
+ "type": "string",
+ "maxLength": 30
+ },
+ "consultation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "representative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ },
+ "notes": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "name",
+ "consultation_status",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "mutationContext": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "operation": {
+ "type": "string",
+ "enum": [
+ "create",
+ "update",
+ "delete",
+ "restore"
+ ]
+ },
+ "actor_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "reason": {
+ "type": "string",
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "if_match": {
+ "type": "string",
+ "minLength": 1
+ },
+ "requested_at": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "operation",
+ "actor_id"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "operation": {
+ "enum": [
+ "update",
+ "delete",
+ "restore"
+ ]
+ }
+ },
+ "required": [
+ "operation"
+ ]
+ },
+ "then": {
+ "required": [
+ "if_match"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "operation": {
+ "const": "delete"
+ }
+ },
+ "required": [
+ "operation"
+ ]
+ },
+ "then": {
+ "required": [
+ "reason"
+ ]
+ }
+ }
+ ]
+ },
+ "apiEnvelope": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "data": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/opportunityResponse"
+ },
+ {
+ "$ref": "#/$defs/locationResponse"
+ },
+ {
+ "$ref": "#/$defs/itemResponse"
+ },
+ {
+ "$ref": "#/$defs/documentResponse"
+ },
+ {
+ "$ref": "#/$defs/evidenceResponse"
+ },
+ {
+ "$ref": "#/$defs/imageResponse"
+ },
+ {
+ "$ref": "#/$defs/localizedPublicationResponse"
+ },
+ {
+ "$ref": "#/$defs/realEstateResponse"
+ },
+ {
+ "$ref": "#/$defs/landRightsResponse"
+ },
+ {
+ "$ref": "#/$defs/businessTransactionResponse"
+ },
+ {
+ "$ref": "#/$defs/parcelResponse"
+ },
+ {
+ "$ref": "#/$defs/improvementResponse"
+ },
+ {
+ "$ref": "#/$defs/communityResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogDefinitionResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogOptionResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogTranslationResponse"
+ },
+ {
+ "$ref": "#/$defs/geoLayerResponse"
+ },
+ {
+ "$ref": "#/$defs/geoFeatureResponse"
+ }
+ ]
+ },
+ "meta": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "request_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "timestamp": {
+ "type": "string",
+ "format": "date-time"
+ }
+ },
+ "required": [
+ "request_id",
+ "timestamp"
+ ]
+ }
+ },
+ "required": [
+ "data",
+ "meta"
+ ]
+ },
+ "pagedResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "data": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ {
+ "$ref": "#/$defs/opportunityResponse"
+ },
+ {
+ "$ref": "#/$defs/locationResponse"
+ },
+ {
+ "$ref": "#/$defs/itemResponse"
+ },
+ {
+ "$ref": "#/$defs/documentResponse"
+ },
+ {
+ "$ref": "#/$defs/evidenceResponse"
+ },
+ {
+ "$ref": "#/$defs/imageResponse"
+ },
+ {
+ "$ref": "#/$defs/localizedPublicationResponse"
+ },
+ {
+ "$ref": "#/$defs/realEstateResponse"
+ },
+ {
+ "$ref": "#/$defs/landRightsResponse"
+ },
+ {
+ "$ref": "#/$defs/businessTransactionResponse"
+ },
+ {
+ "$ref": "#/$defs/parcelResponse"
+ },
+ {
+ "$ref": "#/$defs/improvementResponse"
+ },
+ {
+ "$ref": "#/$defs/communityResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogDefinitionResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogOptionResponse"
+ },
+ {
+ "$ref": "#/$defs/catalogTranslationResponse"
+ },
+ {
+ "$ref": "#/$defs/geoLayerResponse"
+ },
+ {
+ "$ref": "#/$defs/geoFeatureResponse"
+ }
+ ]
+ }
+ },
+ "page": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "page_size": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "total": {
+ "type": "integer",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "data",
+ "page",
+ "page_size",
+ "total"
+ ]
+ },
+ "errorResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "error": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "message": {
+ "type": "string",
+ "minLength": 1
+ },
+ "details": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "field": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "message"
+ ]
+ }
+ }
+ },
+ "required": [
+ "code",
+ "message"
+ ]
+ },
+ "request_id": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "error",
+ "request_id"
+ ]
+ },
+ "createRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "item": {
+ "$ref": "#/$defs/item"
+ }
+ },
+ "required": [
+ "mutation_context",
+ "item"
+ ]
+ },
+ "updateRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "changes": {
+ "type": "object",
+ "minProperties": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "mutation_context",
+ "changes"
+ ]
+ },
+ "deleteRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "mutation_context"
+ ]
+ },
+ "restoreRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "mutation_context"
+ ]
+ },
+ "input": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "input_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "quantity": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ },
+ "source_country": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "name",
+ "input_type"
+ ]
+ },
+ "market": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "market_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "share_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "name",
+ "market_type"
+ ]
+ },
+ "milestone": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date"
+ },
+ "status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "completion_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "due_date",
+ "status"
+ ]
+ },
+ "license": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "authority": {
+ "type": "string",
+ "minLength": 1
+ },
+ "status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "number": {
+ "type": "string"
+ },
+ "issued_at": {
+ "type": "string",
+ "format": "date"
+ },
+ "expires_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "name",
+ "authority",
+ "status"
+ ]
+ },
+ "risk": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "likelihood": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 5
+ },
+ "severity": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 5
+ },
+ "mitigation": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "category",
+ "likelihood",
+ "severity"
+ ]
+ },
+ "relation": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "related_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "relation_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "evidence_ids": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "related_id",
+ "relation_type"
+ ]
+ },
+ "environmentalSocial": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "assessment_status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "environmental_category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "social_risks": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mitigation_plan": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "assessment_status",
+ "environmental_category"
+ ]
+ },
+ "financialIndicators": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ },
+ "capex": {
+ "type": "number",
+ "minimum": 0
+ },
+ "opex": {
+ "type": "number",
+ "minimum": 0
+ },
+ "revenue": {
+ "type": "number",
+ "minimum": 0
+ },
+ "irr_percentage": {
+ "type": "number"
+ },
+ "npv": {
+ "type": "number"
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "currency"
+ ]
+ },
+ "opportunity": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_code": {
+ "type": "string",
+ "pattern": "^INV-MZ-[A-Z0-9]{2,10}-[0-9]{3,}$",
+ "readOnly": true
+ },
+ "opportunity_category": {
+ "enum": [
+ "investment_project",
+ "real_estate",
+ "land_rights",
+ "business_sale",
+ "business_partnership",
+ "franchise",
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ },
+ "official_title": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 150
+ },
+ "alternative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "promoter_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "promoter_type": {
+ "enum": [
+ "public",
+ "private",
+ "ppp",
+ "cooperative",
+ "association",
+ "community",
+ "other"
+ ]
+ },
+ "internal_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "publish_contact": {
+ "type": "boolean",
+ "default": false
+ },
+ "public_contact_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "sector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "subsector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "economic_activity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "location_mode": {
+ "enum": [
+ "single",
+ "multiple"
+ ]
+ },
+ "geographic_scope": {
+ "enum": [
+ "local",
+ "district",
+ "multi_district",
+ "provincial",
+ "interprovincial",
+ "national",
+ "cross_border"
+ ]
+ },
+ "multi_district_rationale": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "locations": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 50,
+ "items": {
+ "$ref": "#/$defs/location"
+ }
+ },
+ "executive_summary": {
+ "type": "string",
+ "minLength": 300,
+ "maxLength": 1500
+ },
+ "demand_statement": {
+ "type": "string",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "opportunity_type": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "maturity_stage": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "investment_modalities": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "investor_profiles": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "products": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/product"
+ }
+ },
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/asset"
+ }
+ },
+ "inputs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/input"
+ }
+ },
+ "markets": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "competitive_advantage": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 100,
+ "maxLength": 1500
+ },
+ "employment": {
+ "$ref": "#/$defs/employment"
+ },
+ "impact_indicators": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/impact"
+ }
+ },
+ "total_investment": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "multipleOf": 0.01
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "secured_financing": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "funding_sought": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "multipleOf": 0.01
+ },
+ "financial_indicators": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "milestones": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "licenses": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "environmental_social": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "risks": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "documents": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/document"
+ }
+ },
+ "evidences": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ },
+ "images": {
+ "type": "array",
+ "maxItems": 20,
+ "items": {
+ "$ref": "#/$defs/image"
+ }
+ },
+ "publication_languages": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": false,
+ "items": {
+ "$ref": "#/$defs/localizedPublication"
+ },
+ "contains": {
+ "properties": {
+ "language_code": {
+ "const": "pt-MZ"
+ }
+ },
+ "required": [
+ "language_code"
+ ]
+ }
+ },
+ "visibility": {
+ "enum": [
+ "internal",
+ "authenticated",
+ "public"
+ ]
+ },
+ "review_due_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "truth_declaration": {
+ "const": true
+ },
+ "real_estate": {
+ "$ref": "#/$defs/realEstate"
+ },
+ "land_rights": {
+ "$ref": "#/$defs/landRights"
+ },
+ "business_transaction": {
+ "$ref": "#/$defs/businessTransaction"
+ },
+ "module_profile_version": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "completion_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100,
+ "readOnly": true
+ },
+ "validation_result": {
+ "type": "object",
+ "readOnly": true
+ },
+ "status": {
+ "enum": [
+ "draft",
+ "submitted",
+ "auto_validation_failed",
+ "technical_review",
+ "legal_territorial_review",
+ "returned",
+ "approval_pending",
+ "approved",
+ "publication_pending",
+ "published",
+ "suspended",
+ "archived",
+ "rejected"
+ ],
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "submitted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "submitted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "approved_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "approved_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "published_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "published_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "archived_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "archived_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ }
+ },
+ "required": [
+ "opportunity_category",
+ "official_title",
+ "promoter_id",
+ "promoter_type",
+ "internal_contact_id",
+ "sector_id",
+ "subsector_id",
+ "economic_activity_id",
+ "location_mode",
+ "geographic_scope",
+ "locations",
+ "executive_summary",
+ "demand_statement",
+ "documents",
+ "evidences",
+ "publication_languages",
+ "visibility",
+ "truth_declaration"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "location_mode": {
+ "const": "multiple"
+ }
+ },
+ "required": [
+ "location_mode"
+ ]
+ },
+ "then": {
+ "properties": {
+ "locations": {
+ "minItems": 2
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "geographic_scope": {
+ "enum": [
+ "multi_district",
+ "interprovincial"
+ ]
+ }
+ },
+ "required": [
+ "geographic_scope"
+ ]
+ },
+ "then": {
+ "required": [
+ "multi_district_rationale"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "publish_contact": {
+ "const": true
+ }
+ },
+ "required": [
+ "publish_contact"
+ ]
+ },
+ "then": {
+ "required": [
+ "public_contact_id"
+ ],
+ "properties": {
+ "public_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "visibility": {
+ "const": "public"
+ }
+ },
+ "required": [
+ "visibility"
+ ]
+ },
+ "then": {
+ "required": [
+ "images",
+ "review_due_date"
+ ],
+ "properties": {
+ "images": {
+ "minItems": 1
+ },
+ "review_due_date": {
+ "type": "string",
+ "format": "date"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "investment_project"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "opportunity_type",
+ "maturity_stage",
+ "investment_modalities",
+ "investor_profiles",
+ "products",
+ "assets",
+ "markets",
+ "competitive_advantage",
+ "employment",
+ "impact_indicators",
+ "total_investment",
+ "currency",
+ "investment_breakdown",
+ "secured_financing",
+ "funding_sought",
+ "milestones",
+ "licenses",
+ "environmental_social",
+ "risks"
+ ],
+ "properties": {
+ "products": {
+ "minItems": 1
+ },
+ "assets": {
+ "minItems": 1
+ },
+ "markets": {
+ "minItems": 1
+ },
+ "employment": {
+ "type": "object"
+ },
+ "impact_indicators": {
+ "minItems": 1
+ },
+ "total_investment": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "minItems": 1
+ },
+ "funding_sought": {
+ "type": "number",
+ "minimum": 0
+ },
+ "milestones": {
+ "minItems": 2
+ },
+ "licenses": {
+ "minItems": 1
+ },
+ "environmental_social": {
+ "type": "object"
+ },
+ "risks": {
+ "minItems": 1
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "real_estate"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "real_estate"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "land_rights"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "land_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "business_sale"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "succession"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "business_partnership"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "enum": [
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "module_profile_version"
+ ]
+ }
+ }
+ ]
+ },
+ "createOpportunityRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "data": {
+ "$ref": "#/$defs/opportunityCreate"
+ }
+ },
+ "required": [
+ "data"
+ ]
+ },
+ "updateOpportunityRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "changes": {
+ "$ref": "#/$defs/opportunityPatch"
+ }
+ },
+ "required": [
+ "mutation_context",
+ "changes"
+ ]
+ },
+ "createResourceRequest": {
+ "type": "object",
+ "properties": {
+ "resource_type": {
+ "enum": [
+ "location",
+ "item",
+ "document",
+ "evidence",
+ "image",
+ "localizedPublication",
+ "realEstate",
+ "landRights",
+ "businessTransaction",
+ "parcel",
+ "improvement",
+ "community",
+ "catalogDefinition",
+ "catalogOption",
+ "catalogTranslation",
+ "geoLayer",
+ "geoFeature"
+ ]
+ },
+ "data": {}
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ],
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "properties": {
+ "resource_type": {
+ "const": "location"
+ },
+ "data": {
+ "$ref": "#/$defs/locationCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "item"
+ },
+ "data": {
+ "$ref": "#/$defs/itemCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "document"
+ },
+ "data": {
+ "$ref": "#/$defs/documentCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "evidence"
+ },
+ "data": {
+ "$ref": "#/$defs/evidenceCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "image"
+ },
+ "data": {
+ "$ref": "#/$defs/imageCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "localizedPublication"
+ },
+ "data": {
+ "$ref": "#/$defs/localizedPublicationCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "realEstate"
+ },
+ "data": {
+ "$ref": "#/$defs/realEstateCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "landRights"
+ },
+ "data": {
+ "$ref": "#/$defs/landRightsCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "businessTransaction"
+ },
+ "data": {
+ "$ref": "#/$defs/businessTransactionCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "parcel"
+ },
+ "data": {
+ "$ref": "#/$defs/parcelCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "improvement"
+ },
+ "data": {
+ "$ref": "#/$defs/improvementCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "community"
+ },
+ "data": {
+ "$ref": "#/$defs/communityCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogDefinition"
+ },
+ "data": {
+ "$ref": "#/$defs/catalogDefinitionCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogOption"
+ },
+ "data": {
+ "$ref": "#/$defs/catalogOptionCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogTranslation"
+ },
+ "data": {
+ "$ref": "#/$defs/catalogTranslationCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "geoLayer"
+ },
+ "data": {
+ "$ref": "#/$defs/geoLayerCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "geoFeature"
+ },
+ "data": {
+ "$ref": "#/$defs/geoFeatureCreate"
+ }
+ },
+ "required": [
+ "resource_type",
+ "data"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "updateResourceRequest": {
+ "type": "object",
+ "properties": {
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "resource_type": {
+ "enum": [
+ "location",
+ "item",
+ "document",
+ "evidence",
+ "image",
+ "localizedPublication",
+ "realEstate",
+ "landRights",
+ "businessTransaction",
+ "parcel",
+ "improvement",
+ "community",
+ "catalogDefinition",
+ "catalogOption",
+ "catalogTranslation",
+ "geoLayer",
+ "geoFeature"
+ ]
+ },
+ "changes": {
+ "type": "object",
+ "minProperties": 1
+ }
+ },
+ "required": [
+ "mutation_context",
+ "resource_type",
+ "changes"
+ ],
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "properties": {
+ "resource_type": {
+ "const": "location"
+ },
+ "changes": {
+ "$ref": "#/$defs/locationPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "item"
+ },
+ "changes": {
+ "$ref": "#/$defs/itemPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "document"
+ },
+ "changes": {
+ "$ref": "#/$defs/documentPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "evidence"
+ },
+ "changes": {
+ "$ref": "#/$defs/evidencePatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "image"
+ },
+ "changes": {
+ "$ref": "#/$defs/imagePatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "localizedPublication"
+ },
+ "changes": {
+ "$ref": "#/$defs/localizedPublicationPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "realEstate"
+ },
+ "changes": {
+ "$ref": "#/$defs/realEstatePatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "landRights"
+ },
+ "changes": {
+ "$ref": "#/$defs/landRightsPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "businessTransaction"
+ },
+ "changes": {
+ "$ref": "#/$defs/businessTransactionPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "parcel"
+ },
+ "changes": {
+ "$ref": "#/$defs/parcelPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "improvement"
+ },
+ "changes": {
+ "$ref": "#/$defs/improvementPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "community"
+ },
+ "changes": {
+ "$ref": "#/$defs/communityPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogDefinition"
+ },
+ "changes": {
+ "$ref": "#/$defs/catalogDefinitionPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogOption"
+ },
+ "changes": {
+ "$ref": "#/$defs/catalogOptionPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "catalogTranslation"
+ },
+ "changes": {
+ "$ref": "#/$defs/catalogTranslationPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "geoLayer"
+ },
+ "changes": {
+ "$ref": "#/$defs/geoLayerPatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ },
+ {
+ "properties": {
+ "resource_type": {
+ "const": "geoFeature"
+ },
+ "changes": {
+ "$ref": "#/$defs/geoFeaturePatch"
+ }
+ },
+ "required": [
+ "resource_type",
+ "changes"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "catalogDefinition": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "is_hierarchical": {
+ "type": "boolean"
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "is_hierarchical",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "catalogOption": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "catalog_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_option_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "catalog_id",
+ "code",
+ "label",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "catalogTranslation": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "catalog_option_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "language_code": {
+ "type": "string",
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "catalog_option_id",
+ "language_code",
+ "label",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "geoLayer": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "srid": {
+ "type": "integer",
+ "const": 4326
+ },
+ "version_label": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "feature_type": {
+ "enum": [
+ "Point",
+ "MultiPoint",
+ "LineString",
+ "MultiLineString",
+ "Polygon",
+ "MultiPolygon",
+ "GeometryCollection"
+ ]
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "feature_type",
+ "srid",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "geoFeature": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "layer_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "geometry": {
+ "type": "object"
+ },
+ "properties": {
+ "type": "object"
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "official_code": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "layer_id",
+ "official_code",
+ "name",
+ "geometry",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "geoValidationRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "geometry": {
+ "type": "object"
+ },
+ "srid": {
+ "type": "integer",
+ "const": 4326
+ },
+ "layer": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "parent_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "checks": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "enum": [
+ "validity",
+ "containment",
+ "intersection",
+ "overlap",
+ "territory"
+ ]
+ }
+ }
+ },
+ "required": [
+ "geometry"
+ ]
+ },
+ "opportunityPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "opportunity_category": {
+ "enum": [
+ "investment_project",
+ "real_estate",
+ "land_rights",
+ "business_sale",
+ "business_partnership",
+ "franchise",
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ },
+ "official_title": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 150
+ },
+ "alternative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "promoter_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "promoter_type": {
+ "enum": [
+ "public",
+ "private",
+ "ppp",
+ "cooperative",
+ "association",
+ "community",
+ "other"
+ ]
+ },
+ "internal_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "publish_contact": {
+ "type": "boolean"
+ },
+ "public_contact_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "sector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "subsector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "economic_activity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "location_mode": {
+ "enum": [
+ "single",
+ "multiple"
+ ]
+ },
+ "geographic_scope": {
+ "enum": [
+ "local",
+ "district",
+ "multi_district",
+ "provincial",
+ "interprovincial",
+ "national",
+ "cross_border"
+ ]
+ },
+ "multi_district_rationale": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "locations": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 50,
+ "items": {
+ "$ref": "#/$defs/location"
+ }
+ },
+ "executive_summary": {
+ "type": "string",
+ "minLength": 300,
+ "maxLength": 1500
+ },
+ "demand_statement": {
+ "type": "string",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "opportunity_type": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "maturity_stage": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "investment_modalities": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "investor_profiles": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "products": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/product"
+ }
+ },
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/asset"
+ }
+ },
+ "inputs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/input"
+ }
+ },
+ "markets": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "competitive_advantage": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 100,
+ "maxLength": 1500
+ },
+ "employment": {
+ "$ref": "#/$defs/employment"
+ },
+ "impact_indicators": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/impact"
+ }
+ },
+ "total_investment": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "multipleOf": 0.01
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "secured_financing": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "funding_sought": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "multipleOf": 0.01
+ },
+ "financial_indicators": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "milestones": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "licenses": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "environmental_social": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "risks": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "documents": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/document"
+ }
+ },
+ "evidences": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ },
+ "images": {
+ "type": "array",
+ "maxItems": 20,
+ "items": {
+ "$ref": "#/$defs/image"
+ }
+ },
+ "publication_languages": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": false,
+ "items": {
+ "$ref": "#/$defs/localizedPublication"
+ },
+ "contains": {
+ "properties": {
+ "language_code": {
+ "const": "pt-MZ"
+ }
+ },
+ "required": [
+ "language_code"
+ ]
+ }
+ },
+ "visibility": {
+ "enum": [
+ "internal",
+ "authenticated",
+ "public"
+ ]
+ },
+ "review_due_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "truth_declaration": {
+ "const": true
+ },
+ "real_estate": {
+ "$ref": "#/$defs/realEstate"
+ },
+ "land_rights": {
+ "$ref": "#/$defs/landRights"
+ },
+ "business_transaction": {
+ "$ref": "#/$defs/businessTransaction"
+ },
+ "module_profile_version": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ }
+ }
+ },
+ "opportunityCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "opportunity_category": {
+ "enum": [
+ "investment_project",
+ "real_estate",
+ "land_rights",
+ "business_sale",
+ "business_partnership",
+ "franchise",
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ },
+ "official_title": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 150
+ },
+ "alternative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "promoter_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "promoter_type": {
+ "enum": [
+ "public",
+ "private",
+ "ppp",
+ "cooperative",
+ "association",
+ "community",
+ "other"
+ ]
+ },
+ "internal_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "publish_contact": {
+ "type": "boolean"
+ },
+ "public_contact_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "sector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "subsector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "economic_activity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "location_mode": {
+ "enum": [
+ "single",
+ "multiple"
+ ]
+ },
+ "geographic_scope": {
+ "enum": [
+ "local",
+ "district",
+ "multi_district",
+ "provincial",
+ "interprovincial",
+ "national",
+ "cross_border"
+ ]
+ },
+ "multi_district_rationale": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "locations": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 50,
+ "items": {
+ "$ref": "#/$defs/location"
+ }
+ },
+ "executive_summary": {
+ "type": "string",
+ "minLength": 300,
+ "maxLength": 1500
+ },
+ "demand_statement": {
+ "type": "string",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "opportunity_type": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "maturity_stage": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "investment_modalities": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "investor_profiles": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "products": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/product"
+ }
+ },
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/asset"
+ }
+ },
+ "inputs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/input"
+ }
+ },
+ "markets": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "competitive_advantage": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 100,
+ "maxLength": 1500
+ },
+ "employment": {
+ "$ref": "#/$defs/employment"
+ },
+ "impact_indicators": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/impact"
+ }
+ },
+ "total_investment": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "multipleOf": 0.01
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "secured_financing": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "funding_sought": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "multipleOf": 0.01
+ },
+ "financial_indicators": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "milestones": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "licenses": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "environmental_social": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "risks": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "documents": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/document"
+ }
+ },
+ "evidences": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ },
+ "images": {
+ "type": "array",
+ "maxItems": 20,
+ "items": {
+ "$ref": "#/$defs/image"
+ }
+ },
+ "publication_languages": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": false,
+ "items": {
+ "$ref": "#/$defs/localizedPublication"
+ },
+ "contains": {
+ "properties": {
+ "language_code": {
+ "const": "pt-MZ"
+ }
+ },
+ "required": [
+ "language_code"
+ ]
+ }
+ },
+ "visibility": {
+ "enum": [
+ "internal",
+ "authenticated",
+ "public"
+ ]
+ },
+ "review_due_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "truth_declaration": {
+ "const": true
+ },
+ "real_estate": {
+ "$ref": "#/$defs/realEstate"
+ },
+ "land_rights": {
+ "$ref": "#/$defs/landRights"
+ },
+ "business_transaction": {
+ "$ref": "#/$defs/businessTransaction"
+ },
+ "module_profile_version": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ }
+ },
+ "required": [
+ "opportunity_category",
+ "official_title",
+ "promoter_id",
+ "promoter_type",
+ "internal_contact_id",
+ "sector_id",
+ "subsector_id",
+ "economic_activity_id",
+ "location_mode",
+ "geographic_scope",
+ "locations",
+ "executive_summary",
+ "demand_statement",
+ "documents",
+ "evidences",
+ "publication_languages",
+ "visibility",
+ "truth_declaration"
+ ]
+ },
+ "opportunityResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_code": {
+ "type": "string",
+ "pattern": "^INV-MZ-[A-Z0-9]{2,10}-[0-9]{3,}$",
+ "readOnly": true
+ },
+ "opportunity_category": {
+ "enum": [
+ "investment_project",
+ "real_estate",
+ "land_rights",
+ "business_sale",
+ "business_partnership",
+ "franchise",
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ },
+ "official_title": {
+ "type": "string",
+ "minLength": 10,
+ "maxLength": 150
+ },
+ "alternative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "promoter_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "promoter_type": {
+ "enum": [
+ "public",
+ "private",
+ "ppp",
+ "cooperative",
+ "association",
+ "community",
+ "other"
+ ]
+ },
+ "internal_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "publish_contact": {
+ "type": "boolean",
+ "default": false
+ },
+ "public_contact_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "sector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "subsector_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "economic_activity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "location_mode": {
+ "enum": [
+ "single",
+ "multiple"
+ ]
+ },
+ "geographic_scope": {
+ "enum": [
+ "local",
+ "district",
+ "multi_district",
+ "provincial",
+ "interprovincial",
+ "national",
+ "cross_border"
+ ]
+ },
+ "multi_district_rationale": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "locations": {
+ "type": "array",
+ "minItems": 1,
+ "maxItems": 50,
+ "items": {
+ "$ref": "#/$defs/location"
+ }
+ },
+ "executive_summary": {
+ "type": "string",
+ "minLength": 300,
+ "maxLength": 1500
+ },
+ "demand_statement": {
+ "type": "string",
+ "minLength": 100,
+ "maxLength": 2000
+ },
+ "opportunity_type": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "maturity_stage": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "investment_modalities": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "investor_profiles": {
+ "type": "array",
+ "uniqueItems": true,
+ "items": {
+ "type": "string"
+ }
+ },
+ "products": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/product"
+ }
+ },
+ "assets": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/asset"
+ }
+ },
+ "inputs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/input"
+ }
+ },
+ "markets": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "competitive_advantage": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 100,
+ "maxLength": 1500
+ },
+ "employment": {
+ "$ref": "#/$defs/employment"
+ },
+ "impact_indicators": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/impact"
+ }
+ },
+ "total_investment": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "multipleOf": 0.01
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "secured_financing": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "funding_sought": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "multipleOf": 0.01
+ },
+ "financial_indicators": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "milestones": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "licenses": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "environmental_social": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "risks": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "relations": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "documents": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/document"
+ }
+ },
+ "evidences": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ },
+ "images": {
+ "type": "array",
+ "maxItems": 20,
+ "items": {
+ "$ref": "#/$defs/image"
+ }
+ },
+ "publication_languages": {
+ "type": "array",
+ "minItems": 1,
+ "uniqueItems": false,
+ "items": {
+ "$ref": "#/$defs/localizedPublication"
+ },
+ "contains": {
+ "properties": {
+ "language_code": {
+ "const": "pt-MZ"
+ }
+ },
+ "required": [
+ "language_code"
+ ]
+ }
+ },
+ "visibility": {
+ "enum": [
+ "internal",
+ "authenticated",
+ "public"
+ ]
+ },
+ "review_due_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "truth_declaration": {
+ "const": true
+ },
+ "real_estate": {
+ "$ref": "#/$defs/realEstate"
+ },
+ "land_rights": {
+ "$ref": "#/$defs/landRights"
+ },
+ "business_transaction": {
+ "$ref": "#/$defs/businessTransaction"
+ },
+ "module_profile_version": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "completion_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100,
+ "readOnly": true
+ },
+ "validation_result": {
+ "type": "object",
+ "readOnly": true
+ },
+ "status": {
+ "enum": [
+ "draft",
+ "submitted",
+ "auto_validation_failed",
+ "technical_review",
+ "legal_territorial_review",
+ "returned",
+ "approval_pending",
+ "approved",
+ "publication_pending",
+ "published",
+ "suspended",
+ "archived",
+ "rejected"
+ ],
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "submitted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "submitted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "approved_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "approved_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "published_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "published_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "archived_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "archived_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "mutation_context": {
+ "$ref": "#/$defs/mutationContext"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ }
+ },
+ "required": [
+ "opportunity_category",
+ "official_title",
+ "promoter_id",
+ "promoter_type",
+ "internal_contact_id",
+ "sector_id",
+ "subsector_id",
+ "economic_activity_id",
+ "location_mode",
+ "geographic_scope",
+ "locations",
+ "executive_summary",
+ "demand_statement",
+ "documents",
+ "evidences",
+ "publication_languages",
+ "visibility",
+ "truth_declaration"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "location_mode": {
+ "const": "multiple"
+ }
+ },
+ "required": [
+ "location_mode"
+ ]
+ },
+ "then": {
+ "properties": {
+ "locations": {
+ "minItems": 2
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "geographic_scope": {
+ "enum": [
+ "multi_district",
+ "interprovincial"
+ ]
+ }
+ },
+ "required": [
+ "geographic_scope"
+ ]
+ },
+ "then": {
+ "required": [
+ "multi_district_rationale"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "publish_contact": {
+ "const": true
+ }
+ },
+ "required": [
+ "publish_contact"
+ ]
+ },
+ "then": {
+ "required": [
+ "public_contact_id"
+ ],
+ "properties": {
+ "public_contact_id": {
+ "type": "string",
+ "format": "uuid"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "visibility": {
+ "const": "public"
+ }
+ },
+ "required": [
+ "visibility"
+ ]
+ },
+ "then": {
+ "required": [
+ "images",
+ "review_due_date"
+ ],
+ "properties": {
+ "images": {
+ "minItems": 1
+ },
+ "review_due_date": {
+ "type": "string",
+ "format": "date"
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "investment_project"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "opportunity_type",
+ "maturity_stage",
+ "investment_modalities",
+ "investor_profiles",
+ "products",
+ "assets",
+ "markets",
+ "competitive_advantage",
+ "employment",
+ "impact_indicators",
+ "total_investment",
+ "currency",
+ "investment_breakdown",
+ "secured_financing",
+ "funding_sought",
+ "milestones",
+ "licenses",
+ "environmental_social",
+ "risks"
+ ],
+ "properties": {
+ "products": {
+ "minItems": 1
+ },
+ "assets": {
+ "minItems": 1
+ },
+ "markets": {
+ "minItems": 1
+ },
+ "employment": {
+ "type": "object"
+ },
+ "impact_indicators": {
+ "minItems": 1
+ },
+ "total_investment": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ },
+ "investment_breakdown": {
+ "minItems": 1
+ },
+ "funding_sought": {
+ "type": "number",
+ "minimum": 0
+ },
+ "milestones": {
+ "minItems": 2
+ },
+ "licenses": {
+ "minItems": 1
+ },
+ "environmental_social": {
+ "type": "object"
+ },
+ "risks": {
+ "minItems": 1
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "real_estate"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "real_estate"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "land_rights"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "land_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "business_sale"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "succession"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "business_partnership"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "business_transaction"
+ ],
+ "properties": {
+ "business_transaction": {
+ "properties": {
+ "transaction_type": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ }
+ }
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "opportunity_category": {
+ "enum": [
+ "concession",
+ "financing",
+ "supply",
+ "other"
+ ]
+ }
+ },
+ "required": [
+ "opportunity_category"
+ ]
+ },
+ "then": {
+ "required": [
+ "module_profile_version"
+ ]
+ }
+ }
+ ]
+ },
+ "locationCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "province_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "district_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "administrative_post_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "locality_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "geometry": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "GeoJSON Geometry in EPSG:4326"
+ },
+ "area_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "sqm",
+ "ha",
+ null
+ ]
+ },
+ "allocation_percentage": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "maximum": 100
+ },
+ "address": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 30
+ },
+ "role_other": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 150
+ },
+ "is_primary": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "province_id",
+ "district_id",
+ "role",
+ "is_primary"
+ ]
+ },
+ "locationPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "province_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "district_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "administrative_post_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "locality_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "geometry": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "GeoJSON Geometry in EPSG:4326"
+ },
+ "area_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "sqm",
+ "ha",
+ null
+ ]
+ },
+ "allocation_percentage": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "maximum": 100
+ },
+ "address": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 30
+ },
+ "role_other": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 150
+ },
+ "is_primary": {
+ "type": "boolean"
+ }
+ }
+ },
+ "locationResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "province_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "district_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "administrative_post_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "locality_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "geometry": {
+ "type": [
+ "object",
+ "null"
+ ],
+ "description": "GeoJSON Geometry in EPSG:4326"
+ },
+ "area_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "sqm",
+ "ha",
+ null
+ ]
+ },
+ "allocation_percentage": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0,
+ "maximum": 100
+ },
+ "address": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 300
+ },
+ "role": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 30
+ },
+ "role_other": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 150
+ },
+ "is_primary": {
+ "type": "boolean"
+ },
+ "active": {
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "required": [
+ "province_id",
+ "district_id",
+ "role",
+ "is_primary"
+ ]
+ },
+ "itemCreate": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "product"
+ },
+ "payload": {
+ "$ref": "#/$defs/productCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "asset"
+ },
+ "payload": {
+ "$ref": "#/$defs/assetCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "input"
+ },
+ "payload": {
+ "$ref": "#/$defs/inputCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "market"
+ },
+ "payload": {
+ "$ref": "#/$defs/marketCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "impact"
+ },
+ "payload": {
+ "$ref": "#/$defs/impactCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "investment"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItemCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "financing"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItemCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "milestone"
+ },
+ "payload": {
+ "$ref": "#/$defs/milestoneCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "license"
+ },
+ "payload": {
+ "$ref": "#/$defs/licenseCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "risk"
+ },
+ "payload": {
+ "$ref": "#/$defs/riskCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "relation"
+ },
+ "payload": {
+ "$ref": "#/$defs/relationCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "employment"
+ },
+ "payload": {
+ "$ref": "#/$defs/employmentCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "environmental_social"
+ },
+ "payload": {
+ "$ref": "#/$defs/environmentalSocialCreate"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ }
+ ]
+ },
+ "itemPatch": {
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "product"
+ },
+ "payload": {
+ "$ref": "#/$defs/product"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "asset"
+ },
+ "payload": {
+ "$ref": "#/$defs/asset"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "input"
+ },
+ "payload": {
+ "$ref": "#/$defs/input"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "market"
+ },
+ "payload": {
+ "$ref": "#/$defs/market"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "impact"
+ },
+ "payload": {
+ "$ref": "#/$defs/impact"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "investment"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "financing"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "milestone"
+ },
+ "payload": {
+ "$ref": "#/$defs/milestone"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "license"
+ },
+ "payload": {
+ "$ref": "#/$defs/license"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "risk"
+ },
+ "payload": {
+ "$ref": "#/$defs/risk"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "relation"
+ },
+ "payload": {
+ "$ref": "#/$defs/relation"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "employment"
+ },
+ "payload": {
+ "$ref": "#/$defs/employment"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "environmental_social"
+ },
+ "payload": {
+ "$ref": "#/$defs/environmentalSocial"
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ }
+ ]
+ }
+ ],
+ "minProperties": 1
+ },
+ "itemResponse": {
+ "oneOf": [
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "product"
+ },
+ "payload": {
+ "$ref": "#/$defs/product"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "asset"
+ },
+ "payload": {
+ "$ref": "#/$defs/asset"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "input"
+ },
+ "payload": {
+ "$ref": "#/$defs/input"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "market"
+ },
+ "payload": {
+ "$ref": "#/$defs/market"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "impact"
+ },
+ "payload": {
+ "$ref": "#/$defs/impact"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "investment"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "financing"
+ },
+ "payload": {
+ "$ref": "#/$defs/moneyItem"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "milestone"
+ },
+ "payload": {
+ "$ref": "#/$defs/milestone"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "license"
+ },
+ "payload": {
+ "$ref": "#/$defs/license"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "risk"
+ },
+ "payload": {
+ "$ref": "#/$defs/risk"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "relation"
+ },
+ "payload": {
+ "$ref": "#/$defs/relation"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "employment"
+ },
+ "payload": {
+ "$ref": "#/$defs/employment"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ },
+ {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "item_type": {
+ "const": "environmental_social"
+ },
+ "payload": {
+ "$ref": "#/$defs/environmentalSocial"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ }
+ },
+ "required": [
+ "item_type",
+ "payload"
+ ]
+ }
+ ]
+ },
+ "documentCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "mime_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "confidential": {
+ "type": "boolean"
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "original_name": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "title",
+ "category",
+ "original_name"
+ ]
+ },
+ "documentPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "mime_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "confidential": {
+ "type": "boolean"
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "original_name": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "documentResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "mime_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "confidential": {
+ "type": "boolean"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "original_name": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "category",
+ "original_name",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "evidenceCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "evidence_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "document_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "verified": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "title",
+ "evidence_type"
+ ]
+ },
+ "evidencePatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "evidence_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "document_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "verified": {
+ "type": "boolean"
+ }
+ }
+ },
+ "evidenceResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "evidence_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "document_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "verified": {
+ "type": "boolean"
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "title",
+ "evidence_type",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "imageCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "alt_text": {
+ "type": "string",
+ "minLength": 1
+ },
+ "is_cover": {
+ "type": "boolean"
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ }
+ },
+ "required": [
+ "url",
+ "alt_text"
+ ]
+ },
+ "imagePatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "alt_text": {
+ "type": "string",
+ "minLength": 1
+ },
+ "is_cover": {
+ "type": "boolean"
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ }
+ }
+ },
+ "imageResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ },
+ "alt_text": {
+ "type": "string",
+ "minLength": 1
+ },
+ "is_cover": {
+ "type": "boolean"
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "id",
+ "version",
+ "is_deleted",
+ "url",
+ "alt_text",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "localizedPublicationCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "language_code": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "summary": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "language_code",
+ "title",
+ "summary"
+ ]
+ },
+ "localizedPublicationPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "language_code": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "summary": {
+ "type": "string"
+ }
+ }
+ },
+ "localizedPublicationResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "language_code": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "summary": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "opportunity_id",
+ "language_code",
+ "title",
+ "summary",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "realEstateCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "sale",
+ "lease",
+ "investment",
+ "development",
+ "partnership"
+ ]
+ },
+ "property_type": {
+ "enum": [
+ "house",
+ "apartment",
+ "office",
+ "retail",
+ "warehouse",
+ "hospitality",
+ "industrial",
+ "mixed_use",
+ "development",
+ "other"
+ ]
+ },
+ "construction_status": {
+ "enum": [
+ "planned",
+ "under_construction",
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ },
+ "property_condition": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "new",
+ "good",
+ "fair",
+ "poor",
+ "derelict",
+ null
+ ]
+ },
+ "land_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "built_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "enum": [
+ "sqm",
+ "ha"
+ ]
+ },
+ "units": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "rooms": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "floors": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "amenities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "utilities": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "occupancy_status": {
+ "enum": [
+ "vacant",
+ "owner_occupied",
+ "tenant_occupied",
+ "partially_occupied"
+ ]
+ },
+ "title_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "registration_number": {
+ "type": "string",
+ "minLength": 1
+ },
+ "encumbrances": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "price": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent_periodicity": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "monthly",
+ "quarterly",
+ "semiannual",
+ "annual",
+ "other",
+ null
+ ]
+ },
+ "deposit": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "viewing": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "planning_permit_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "use_license_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "transaction_type",
+ "property_type",
+ "construction_status",
+ "land_area",
+ "built_area",
+ "area_unit",
+ "utilities",
+ "occupancy_status",
+ "title_type",
+ "registration_number",
+ "encumbrances",
+ "valuation"
+ ]
+ },
+ "realEstatePatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "sale",
+ "lease",
+ "investment",
+ "development",
+ "partnership"
+ ]
+ },
+ "property_type": {
+ "enum": [
+ "house",
+ "apartment",
+ "office",
+ "retail",
+ "warehouse",
+ "hospitality",
+ "industrial",
+ "mixed_use",
+ "development",
+ "other"
+ ]
+ },
+ "construction_status": {
+ "enum": [
+ "planned",
+ "under_construction",
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ },
+ "property_condition": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "new",
+ "good",
+ "fair",
+ "poor",
+ "derelict",
+ null
+ ]
+ },
+ "land_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "built_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "enum": [
+ "sqm",
+ "ha"
+ ]
+ },
+ "units": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "rooms": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "floors": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "amenities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "utilities": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "occupancy_status": {
+ "enum": [
+ "vacant",
+ "owner_occupied",
+ "tenant_occupied",
+ "partially_occupied"
+ ]
+ },
+ "title_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "registration_number": {
+ "type": "string",
+ "minLength": 1
+ },
+ "encumbrances": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "price": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent_periodicity": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "monthly",
+ "quarterly",
+ "semiannual",
+ "annual",
+ "other",
+ null
+ ]
+ },
+ "deposit": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "viewing": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "planning_permit_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "use_license_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ }
+ },
+ "realEstateResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "transaction_type": {
+ "enum": [
+ "sale",
+ "lease",
+ "investment",
+ "development",
+ "partnership"
+ ]
+ },
+ "property_type": {
+ "enum": [
+ "house",
+ "apartment",
+ "office",
+ "retail",
+ "warehouse",
+ "hospitality",
+ "industrial",
+ "mixed_use",
+ "development",
+ "other"
+ ]
+ },
+ "construction_status": {
+ "enum": [
+ "planned",
+ "under_construction",
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ },
+ "property_condition": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "new",
+ "good",
+ "fair",
+ "poor",
+ "derelict",
+ null
+ ]
+ },
+ "land_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "built_area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "area_unit": {
+ "enum": [
+ "sqm",
+ "ha"
+ ]
+ },
+ "units": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "rooms": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "floors": {
+ "type": [
+ "integer",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "amenities": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "utilities": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "occupancy_status": {
+ "enum": [
+ "vacant",
+ "owner_occupied",
+ "tenant_occupied",
+ "partially_occupied"
+ ]
+ },
+ "title_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "registration_number": {
+ "type": "string",
+ "minLength": 1
+ },
+ "encumbrances": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "price": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0
+ },
+ "rent_periodicity": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "enum": [
+ "monthly",
+ "quarterly",
+ "semiannual",
+ "annual",
+ "other",
+ null
+ ]
+ },
+ "deposit": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "viewing": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "planning_permit_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "use_license_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "transaction_type",
+ "property_type",
+ "construction_status",
+ "land_area",
+ "built_area",
+ "area_unit",
+ "utilities",
+ "occupancy_status",
+ "title_type",
+ "registration_number",
+ "encumbrances",
+ "valuation"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "sale"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "price"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "lease"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "rent",
+ "rent_periodicity"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "construction_status": {
+ "enum": [
+ "completed",
+ "occupied",
+ "renovation"
+ ]
+ }
+ },
+ "required": [
+ "construction_status"
+ ]
+ },
+ "then": {
+ "required": [
+ "property_condition"
+ ]
+ }
+ }
+ ]
+ },
+ "landRightsCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "operation_type": {
+ "enum": [
+ "investment_with_duat",
+ "transfer_of_improvements",
+ "assignment_subject_to_authorization",
+ "lease_of_improvements",
+ "operating_partnership",
+ "other_legal"
+ ]
+ },
+ "duat_status": {
+ "enum": [
+ "none",
+ "application",
+ "provisional",
+ "definitive",
+ "occupancy_recognition",
+ "community_right"
+ ]
+ },
+ "duat_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "holder_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "holder_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "issuing_authority_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "issue_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "expiry_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "authorized_purpose": {
+ "type": "string",
+ "minLength": 1
+ },
+ "exploitation_plan_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "parcels": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/parcelCreate"
+ }
+ },
+ "improvements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/improvementCreate"
+ }
+ },
+ "communities": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/communityCreate"
+ }
+ },
+ "community_consultation": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "overlaps_conflicts": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "required_authorizations": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "consideration": {
+ "type": [
+ "object",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "operation_type",
+ "duat_status",
+ "holder_name",
+ "authorized_purpose",
+ "parcels",
+ "overlaps_conflicts",
+ "required_authorizations"
+ ]
+ },
+ "landRightsPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "operation_type": {
+ "enum": [
+ "investment_with_duat",
+ "transfer_of_improvements",
+ "assignment_subject_to_authorization",
+ "lease_of_improvements",
+ "operating_partnership",
+ "other_legal"
+ ]
+ },
+ "duat_status": {
+ "enum": [
+ "none",
+ "application",
+ "provisional",
+ "definitive",
+ "occupancy_recognition",
+ "community_right"
+ ]
+ },
+ "duat_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "holder_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "holder_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "issuing_authority_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "issue_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "expiry_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "authorized_purpose": {
+ "type": "string",
+ "minLength": 1
+ },
+ "exploitation_plan_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "parcels": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/parcelCreate"
+ }
+ },
+ "improvements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/improvementCreate"
+ }
+ },
+ "communities": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/communityCreate"
+ }
+ },
+ "community_consultation": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "overlaps_conflicts": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "required_authorizations": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "consideration": {
+ "type": [
+ "object",
+ "null"
+ ]
+ }
+ }
+ },
+ "landRightsResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "operation_type": {
+ "enum": [
+ "investment_with_duat",
+ "transfer_of_improvements",
+ "assignment_subject_to_authorization",
+ "lease_of_improvements",
+ "operating_partnership",
+ "other_legal"
+ ]
+ },
+ "duat_status": {
+ "enum": [
+ "none",
+ "application",
+ "provisional",
+ "definitive",
+ "occupancy_recognition",
+ "community_right"
+ ]
+ },
+ "duat_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "holder_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "holder_name": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 200
+ },
+ "issuing_authority_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "issue_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "expiry_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "authorized_purpose": {
+ "type": "string",
+ "minLength": 1
+ },
+ "exploitation_plan_document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "parcels": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "$ref": "#/$defs/parcelResponse"
+ }
+ },
+ "improvements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/improvementResponse"
+ }
+ },
+ "communities": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/communityResponse"
+ }
+ },
+ "community_consultation": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "overlaps_conflicts": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "required_authorizations": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "consideration": {
+ "type": [
+ "object",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "operation_type",
+ "duat_status",
+ "holder_name",
+ "authorized_purpose",
+ "parcels",
+ "overlaps_conflicts",
+ "required_authorizations"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "duat_status": {
+ "enum": [
+ "provisional",
+ "definitive"
+ ]
+ }
+ },
+ "required": [
+ "duat_status"
+ ]
+ },
+ "then": {
+ "required": [
+ "duat_number",
+ "issuing_authority_id"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "operation_type": {
+ "enum": [
+ "transfer_of_improvements",
+ "lease_of_improvements"
+ ]
+ }
+ },
+ "required": [
+ "operation_type"
+ ]
+ },
+ "then": {
+ "properties": {
+ "improvements": {
+ "minItems": 1
+ }
+ },
+ "required": [
+ "improvements",
+ "consideration"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "operation_type": {
+ "const": "operating_partnership"
+ }
+ },
+ "required": [
+ "operation_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "consideration"
+ ]
+ }
+ }
+ ]
+ },
+ "businessTransactionCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "partnership",
+ "joint_venture",
+ "franchise",
+ "succession",
+ "financing"
+ ]
+ },
+ "legal_entity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "legal_form": {
+ "type": "string",
+ "minLength": 1
+ },
+ "percentage_offered": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "maximum": 100
+ },
+ "asking_price": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "financial_periods": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "assets_liabilities": {
+ "type": "object"
+ },
+ "employees": {
+ "type": "object"
+ },
+ "contracts_licenses": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "litigation_contingencies": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "reason_for_transaction": {
+ "type": "string",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "partner_contribution": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "governance_rights": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "franchise_terms": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "confidentiality_level": {
+ "enum": [
+ "teaser",
+ "nda_required",
+ "restricted"
+ ]
+ },
+ "due_diligence_status": {
+ "enum": [
+ "not_started",
+ "data_room_ready",
+ "in_progress",
+ "completed",
+ "exceptions"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type",
+ "legal_entity_id",
+ "legal_form",
+ "asking_price",
+ "valuation",
+ "financial_periods",
+ "assets_liabilities",
+ "employees",
+ "contracts_licenses",
+ "litigation_contingencies",
+ "reason_for_transaction",
+ "confidentiality_level",
+ "due_diligence_status"
+ ]
+ },
+ "businessTransactionPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "partnership",
+ "joint_venture",
+ "franchise",
+ "succession",
+ "financing"
+ ]
+ },
+ "legal_entity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "legal_form": {
+ "type": "string",
+ "minLength": 1
+ },
+ "percentage_offered": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "maximum": 100
+ },
+ "asking_price": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "financial_periods": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "assets_liabilities": {
+ "type": "object"
+ },
+ "employees": {
+ "type": "object"
+ },
+ "contracts_licenses": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "litigation_contingencies": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "reason_for_transaction": {
+ "type": "string",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "partner_contribution": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "governance_rights": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "franchise_terms": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "confidentiality_level": {
+ "enum": [
+ "teaser",
+ "nda_required",
+ "restricted"
+ ]
+ },
+ "due_diligence_status": {
+ "enum": [
+ "not_started",
+ "data_room_ready",
+ "in_progress",
+ "completed",
+ "exceptions"
+ ]
+ }
+ }
+ },
+ "businessTransactionResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "default": false,
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "transaction_type": {
+ "enum": [
+ "full_sale",
+ "partial_sale",
+ "partnership",
+ "joint_venture",
+ "franchise",
+ "succession",
+ "financing"
+ ]
+ },
+ "legal_entity_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "legal_form": {
+ "type": "string",
+ "minLength": 1
+ },
+ "percentage_offered": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "exclusiveMinimum": 0,
+ "maximum": 100
+ },
+ "asking_price": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "valuation": {
+ "type": "object"
+ },
+ "financial_periods": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "assets_liabilities": {
+ "type": "object"
+ },
+ "employees": {
+ "type": "object"
+ },
+ "contracts_licenses": {
+ "type": "array",
+ "minItems": 1,
+ "items": {
+ "type": "object"
+ }
+ },
+ "litigation_contingencies": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "reason_for_transaction": {
+ "type": "string",
+ "minLength": 50,
+ "maxLength": 1000
+ },
+ "partner_contribution": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "governance_rights": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "franchise_terms": {
+ "type": [
+ "object",
+ "null"
+ ]
+ },
+ "confidentiality_level": {
+ "enum": [
+ "teaser",
+ "nda_required",
+ "restricted"
+ ]
+ },
+ "due_diligence_status": {
+ "enum": [
+ "not_started",
+ "data_room_ready",
+ "in_progress",
+ "completed",
+ "exceptions"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type",
+ "legal_entity_id",
+ "legal_form",
+ "asking_price",
+ "valuation",
+ "financial_periods",
+ "assets_liabilities",
+ "employees",
+ "contracts_licenses",
+ "litigation_contingencies",
+ "reason_for_transaction",
+ "confidentiality_level",
+ "due_diligence_status"
+ ],
+ "allOf": [
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "full_sale"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "properties": {
+ "percentage_offered": {
+ "const": 100
+ }
+ },
+ "required": [
+ "percentage_offered",
+ "governance_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partial_sale",
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "percentage_offered",
+ "governance_rights"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "enum": [
+ "partnership",
+ "joint_venture"
+ ]
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "partner_contribution"
+ ]
+ }
+ },
+ {
+ "if": {
+ "properties": {
+ "transaction_type": {
+ "const": "franchise"
+ }
+ },
+ "required": [
+ "transaction_type"
+ ]
+ },
+ "then": {
+ "required": [
+ "franchise_terms"
+ ]
+ }
+ }
+ ]
+ },
+ "parcelCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cadastral_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "location_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "geometry": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "MultiPolygon"
+ },
+ "coordinates": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type",
+ "coordinates"
+ ]
+ },
+ "overlap_status": {
+ "type": "string",
+ "maxLength": 30
+ }
+ },
+ "required": [
+ "location_id",
+ "area",
+ "geometry",
+ "overlap_status"
+ ]
+ },
+ "parcelPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "cadastral_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "location_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "geometry": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "MultiPolygon"
+ },
+ "coordinates": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type",
+ "coordinates"
+ ]
+ },
+ "overlap_status": {
+ "type": "string",
+ "maxLength": 30
+ }
+ }
+ },
+ "parcelResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "cadastral_number": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 120
+ },
+ "location_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "area": {
+ "type": "number",
+ "exclusiveMinimum": 0
+ },
+ "geometry": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "type": {
+ "const": "MultiPolygon"
+ },
+ "coordinates": {
+ "type": "array"
+ }
+ },
+ "required": [
+ "type",
+ "coordinates"
+ ]
+ },
+ "overlap_status": {
+ "type": "string",
+ "maxLength": 30
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "location_id",
+ "area",
+ "geometry",
+ "overlap_status",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "improvementCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "improvement_type": {
+ "type": "string",
+ "maxLength": 60
+ },
+ "owner_name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "assessed_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "valuation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "image_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "improvement_type",
+ "owner_name"
+ ]
+ },
+ "improvementPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "improvement_type": {
+ "type": "string",
+ "maxLength": 60
+ },
+ "owner_name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "assessed_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "valuation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "image_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ }
+ },
+ "improvementResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "improvement_type": {
+ "type": "string",
+ "maxLength": 60
+ },
+ "owner_name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "assessed_value": {
+ "type": [
+ "number",
+ "null"
+ ],
+ "minimum": 0
+ },
+ "currency": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "pattern": "^[A-Z]{3}$"
+ },
+ "valuation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "document_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "image_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "improvement_type",
+ "owner_name",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "communityCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "consultation_status": {
+ "type": "string",
+ "maxLength": 30
+ },
+ "consultation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "representative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ },
+ "notes": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "consultation_status"
+ ]
+ },
+ "communityPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "consultation_status": {
+ "type": "string",
+ "maxLength": 30
+ },
+ "consultation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "representative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ },
+ "notes": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ },
+ "communityResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "opportunity_id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "name": {
+ "type": "string",
+ "maxLength": 200
+ },
+ "location_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "consultation_status": {
+ "type": "string",
+ "maxLength": 30
+ },
+ "consultation_date": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ },
+ "representative_name": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "maxLength": 200
+ },
+ "notes": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "id",
+ "opportunity_id",
+ "name",
+ "consultation_status",
+ "version",
+ "active",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "catalogDefinitionCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "is_hierarchical": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "is_hierarchical"
+ ]
+ },
+ "catalogDefinitionPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "is_hierarchical": {
+ "type": "boolean"
+ }
+ }
+ },
+ "catalogDefinitionResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "is_hierarchical": {
+ "type": "boolean"
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "is_hierarchical",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "catalogOptionCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "catalog_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_option_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "catalog_id",
+ "code",
+ "label"
+ ]
+ },
+ "catalogOptionPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "catalog_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_option_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ }
+ },
+ "catalogOptionResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "sort_order": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "catalog_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_option_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ }
+ },
+ "required": [
+ "catalog_id",
+ "code",
+ "label",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "catalogTranslationCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "catalog_option_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "language_code": {
+ "type": "string",
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "catalog_option_id",
+ "language_code",
+ "label"
+ ]
+ },
+ "catalogTranslationPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "catalog_option_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "language_code": {
+ "type": "string",
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ }
+ },
+ "catalogTranslationResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "catalog_option_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "language_code": {
+ "type": "string",
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
+ },
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
+ "required": [
+ "catalog_option_id",
+ "language_code",
+ "label",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "geoLayerCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "srid": {
+ "type": "integer",
+ "const": 4326
+ },
+ "version_label": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "feature_type": {
+ "enum": [
+ "Point",
+ "MultiPoint",
+ "LineString",
+ "MultiLineString",
+ "Polygon",
+ "MultiPolygon",
+ "GeometryCollection"
+ ]
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "feature_type",
+ "srid"
+ ]
+ },
+ "geoLayerPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "srid": {
+ "type": "integer",
+ "const": 4326
+ },
+ "version_label": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "feature_type": {
+ "enum": [
+ "Point",
+ "MultiPoint",
+ "LineString",
+ "MultiLineString",
+ "Polygon",
+ "MultiPolygon",
+ "GeometryCollection"
+ ]
+ }
+ }
+ },
+ "geoLayerResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "srid": {
+ "type": "integer",
+ "const": 4326
+ },
+ "version_label": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "feature_type": {
+ "enum": [
+ "Point",
+ "MultiPoint",
+ "LineString",
+ "MultiLineString",
+ "Polygon",
+ "MultiPolygon",
+ "GeometryCollection"
+ ]
+ }
+ },
+ "required": [
+ "code",
+ "name",
+ "feature_type",
+ "srid",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "geoFeatureCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "layer_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "geometry": {
+ "type": "object"
+ },
+ "properties": {
+ "type": "object"
+ },
+ "official_code": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "layer_id",
+ "official_code",
+ "name",
+ "geometry"
+ ]
+ },
+ "geoFeaturePatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "minProperties": 1,
+ "properties": {
+ "layer_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "geometry": {
+ "type": "object"
+ },
+ "properties": {
+ "type": "object"
+ },
+ "official_code": {
+ "type": "string",
+ "minLength": 1
+ }
+ }
+ },
+ "geoFeatureResponse": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "version": {
+ "type": "integer",
+ "minimum": 1,
+ "readOnly": true
+ },
+ "is_deleted": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "deleted_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date-time",
+ "readOnly": true
+ },
+ "deleted_by": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid",
+ "readOnly": true
+ },
+ "delete_reason": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "minLength": 20,
+ "maxLength": 1000,
+ "readOnly": true
+ },
+ "created_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "created_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "updated_by": {
+ "type": "string",
+ "format": "uuid",
+ "readOnly": true
+ },
+ "updated_at": {
+ "type": "string",
+ "format": "date-time",
+ "readOnly": true
+ },
+ "layer_id": {
+ "type": "string",
+ "format": "uuid"
+ },
+ "parent_id": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "uuid"
+ },
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "geometry": {
+ "type": "object"
+ },
+ "properties": {
+ "type": "object"
+ },
+ "active": {
+ "type": "boolean",
+ "readOnly": true
+ },
+ "official_code": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "layer_id",
+ "official_code",
+ "name",
+ "geometry",
+ "active",
+ "id",
+ "version",
+ "is_deleted",
+ "created_by",
+ "created_at",
+ "updated_by",
+ "updated_at"
+ ]
+ },
+ "productCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "code": {
+ "type": "string",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "quantity": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "name",
+ "category"
+ ]
+ },
+ "assetCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "asset_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "value": {
+ "type": "number",
+ "minimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ }
+ },
+ "required": [
+ "name",
+ "asset_type"
+ ]
+ },
+ "inputCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "input_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "quantity": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ },
+ "source_country": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ }
+ },
+ "required": [
+ "name",
+ "input_type"
+ ]
+ },
+ "marketCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "market_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "country_code": {
+ "type": "string",
+ "pattern": "^[A-Z]{2}$"
+ },
+ "share_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "name",
+ "market_type"
+ ]
+ },
+ "impactCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "impact_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string",
+ "minLength": 1
+ },
+ "indicator": {
+ "type": "string",
+ "minLength": 1
+ },
+ "target": {
+ "type": "number"
+ },
+ "unit": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "impact_type",
+ "description"
+ ]
+ },
+ "moneyItemCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "label": {
+ "type": "string",
+ "minLength": 1
+ },
+ "amount": {
+ "type": "number",
+ "minimum": 0
+ },
+ "currency": {
+ "type": "string",
+ "pattern": "^[A-Z]{3}$"
+ },
+ "year": {
+ "type": "integer",
+ "minimum": 1900
+ }
+ },
+ "required": [
+ "label",
+ "amount",
+ "currency"
+ ]
+ },
+ "milestoneCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "due_date": {
+ "type": "string",
+ "format": "date"
+ },
+ "status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "completion_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "title",
+ "due_date",
+ "status"
+ ]
+ },
+ "licenseCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1
+ },
+ "authority": {
+ "type": "string",
+ "minLength": 1
+ },
+ "status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "number": {
+ "type": "string"
+ },
+ "issued_at": {
+ "type": "string",
+ "format": "date"
+ },
+ "expires_at": {
+ "type": [
+ "string",
+ "null"
+ ],
+ "format": "date"
+ }
+ },
+ "required": [
+ "name",
+ "authority",
+ "status"
+ ]
+ },
+ "riskCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "title": {
+ "type": "string",
+ "minLength": 1
+ },
+ "category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "likelihood": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 5
+ },
+ "severity": {
+ "type": "integer",
+ "minimum": 1,
+ "maximum": 5
+ },
+ "mitigation": {
+ "type": "string",
+ "minLength": 1
+ }
+ },
+ "required": [
+ "title",
+ "category",
+ "likelihood",
+ "severity"
+ ]
+ },
+ "relationCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "related_id": {
+ "type": "string",
+ "minLength": 1
+ },
+ "relation_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "description": {
+ "type": "string"
+ },
+ "evidence_ids": {
+ "type": "array",
+ "items": {
+ "$ref": "#/$defs/evidence"
+ }
+ }
+ },
+ "required": [
+ "related_id",
+ "relation_type"
+ ]
+ },
+ "employmentCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "employment_type": {
+ "type": "string",
+ "minLength": 1
+ },
+ "direct_jobs": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "indirect_jobs": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "female_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ },
+ "youth_percentage": {
+ "type": "number",
+ "minimum": 0,
+ "maximum": 100
+ }
+ },
+ "required": [
+ "employment_type",
+ "direct_jobs"
+ ]
+ },
+ "environmentalSocialCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "assessment_status": {
+ "type": "string",
+ "minLength": 1
+ },
+ "environmental_category": {
+ "type": "string",
+ "minLength": 1
+ },
+ "social_risks": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "mitigation_plan": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "assessment_status",
+ "environmental_category"
+]
+ }
+ },
+ "$ref": "#/$defs/opportunityResponse"
+}
diff --git a/resources/data/investmoz-opportunity-modular.source.json b/resources/data/investmoz-opportunity-modular.source.json
new file mode 100644
index 00000000..a77d5103
--- /dev/null
+++ b/resources/data/investmoz-opportunity-modular.source.json
@@ -0,0 +1,25 @@
+{
+ "source_document_sha256": "9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504",
+ "source_paragraphs": "2110–14681 (§26)",
+ "artifact_sha256": "9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0",
+ "definitions": 110,
+ "schema_dialect": "https://json-schema.org/draft/2020-12/schema",
+ "core_id_compatibility": "Normative UUID examples retained; existing opportunity bigint IDs must use an explicit adapter, never a renumbering migration.",
+ "contracts": [
+ "realEstateCreate",
+ "realEstatePatch",
+ "realEstateResponse",
+ "landRightsCreate",
+ "landRightsPatch",
+ "landRightsResponse",
+ "businessTransactionCreate",
+ "businessTransactionPatch",
+ "businessTransactionResponse"
+ ],
+ "runtime_validation_implemented": false,
+ "workflow_implemented": false,
+ "qa_activation": false,
+ "active_writes": 0,
+ "state_scope": "Historical extraction snapshot before the runtime adapter. These booleans are not current runtime/installation flags.",
+ "current_runtime_reference": "docs/investmoz/v2/auditoria-portal/workflow-oportunidades-qa.md"
+}
diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx
index d50e92cf..e2ed18a3 100644
--- a/resources/js/components/app-sidebar.tsx
+++ b/resources/js/components/app-sidebar.tsx
@@ -1,3 +1,5 @@
+import { profileLinks } from '@/components/profile-navigation';
+import type { ProfileAccess } from '@/types/profile-access';
import { Link, usePage } from '@inertiajs/react';
import { LayoutGrid } from 'lucide-react';
import { portalNavigation } from '@/lib/portal-navigation';
@@ -15,27 +17,52 @@ import {
} from '@/components/ui/sidebar';
import { dashboard } from '@/routes';
import type { Auth } from '@/types';
+import type { OpportunityManagementAccess } from '@/types/opportunity-management';
export function AppSidebar() {
- const { auth, existingBusinessEnabled, educationEnabled, aiEnabled } =
- usePage<{
- auth: Auth;
- existingBusinessEnabled?: boolean;
- educationEnabled?: boolean;
- aiEnabled?: boolean;
- }>().props;
+ const {
+ auth,
+ existingBusinessEnabled,
+ educationEnabled,
+ aiEnabled,
+ opportunityManagement,
+ profileAccess,
+ } = usePage<{
+ auth: Auth;
+ existingBusinessEnabled?: boolean;
+ educationEnabled?: boolean;
+ aiEnabled?: boolean;
+ profileAccess?: ProfileAccess | null;
+ opportunityManagement?: OpportunityManagementAccess | null;
+ }>().props;
const groups = portalNavigation({
authenticated: !!auth.user,
manager: auth.canManagePortal,
businesses: existingBusinessEnabled,
education: educationEnabled,
ai: aiEnabled,
+ opportunityManagement,
});
const items = groups.map((group) => ({
title: group.label,
href: group.children?.find((item) => item.href)?.href ?? '/',
icon: LayoutGrid,
}));
+ if (auth.canManagePortal && opportunityManagement) {
+ items.push({
+ title: opportunityManagement.manage.label,
+ href: opportunityManagement.manage.href,
+ icon: LayoutGrid,
+ });
+ if (opportunityManagement.installed) {
+ items.push({
+ title: opportunityManagement.create.label,
+ href: opportunityManagement.create.href,
+ icon: LayoutGrid,
+ });
+ }
+ }
+ items.push(...profileLinks(profileAccess).map(link => ({...link, icon: LayoutGrid})));
return (
diff --git a/resources/js/components/investment-territory.tsx b/resources/js/components/investment-territory.tsx
index fdedaef4..3baecc81 100644
--- a/resources/js/components/investment-territory.tsx
+++ b/resources/js/components/investment-territory.tsx
@@ -40,6 +40,30 @@ export function ProvinceSelect({
const [error, setError] = useState('');
const [retry, setRetry] = useState(0);
const [search, setSearch] = useState('');
+ const [geometrySelection, setGeometrySelection] = useState<{ value: string; id: string } | null>(null);
+ const [geometryFeedback, setGeometryFeedback] = useState('');
+
+ useEffect(() => {
+ const controller = new AbortController();
+ setGeometrySelection(null);
+ setGeometryFeedback('');
+ if (!value) return;
+ // Preserve historical text. Only one exact catalogue match supplies a map ID.
+ void fetch(`${endpoint}?${new URLSearchParams({ type: 'province', page: '1', q: value })}`, {
+ signal: controller.signal, headers: { Accept: 'application/json' },
+ }).then(async (response) => {
+ if (!response.ok) throw new Error('Não foi possível consultar a correspondência cartográfica.');
+ const data = await response.json();
+ const matches = (data.data as Option[]).filter((option) => option.name === value);
+ if (controller.signal.aborted) return;
+ if (matches.length === 1 && !data.next_page_url)
+ setGeometrySelection({ value, id: matches[0].id });
+ else setGeometryFeedback('Seleção guardada preservada; sem correspondência cartográfica inequívoca neste cadastro.');
+ }).catch((cause: unknown) => {
+ if (!controller.signal.aborted) setGeometryFeedback(cause instanceof Error ? cause.message : 'Erro de ligação.');
+ });
+ return () => controller.abort();
+ }, [endpoint, value, retry]);
useEffect(() => {
const controller = new AbortController();
@@ -127,6 +151,12 @@ export function ProvinceSelect({
)}
+ {geometryFeedback && {geometryFeedback}
}
+
>
);
}
@@ -181,6 +211,7 @@ export function TerritoryFields({
);
diff --git a/resources/js/components/opportunity-canonical-fields.tsx b/resources/js/components/opportunity-canonical-fields.tsx
new file mode 100644
index 00000000..1ee5628c
--- /dev/null
+++ b/resources/js/components/opportunity-canonical-fields.tsx
@@ -0,0 +1,750 @@
+import OpportunityParcelGeometry from "./opportunity-parcel-geometry";
+import TerritoryGeometryPreview from "./territory-geometry-preview";
+import { control } from "@/pages/management/shared";
+
+type Data = Record;
+type Schema = {
+ $ref?: string;
+ type?: string | string[];
+ properties?: Record;
+ items?: Schema;
+ enum?: unknown[];
+ const?: unknown;
+ format?: string;
+ maxLength?: number;
+ required?: string[];
+};
+type Resource = {
+ id: string;
+ payload: { title?: string; role?: string; [key: string]: unknown };
+ file?: { file_name: string };
+};
+function resourceTerritory(resource?: Resource) {
+ const p = resource?.payload;
+ const id =
+ p?.locality_id ?? p?.admin_post_id ?? p?.district_id ?? p?.province_id;
+ return typeof id === "string" ? id : undefined;
+}
+export type CanonicalOptions = {
+ version: string;
+ schema: Schema;
+ definitions: Record;
+ contacts: { id: string; full_name: string }[];
+ activities: {
+ id: string;
+ parent_id: string | null;
+ sector_id: number;
+ label_pt_mz: string;
+ }[];
+ resources: Record;
+ gates: string[];
+ countries: { code: string; name: string }[];
+ authorities: { id: string; label_pt_mz: string }[];
+};
+const labels: Record = {
+ official_title: "Título oficial",
+ promoter_type: "Tipo de Promotor",
+ internal_contact_id: "Contacto interno",
+ sector_id: "Sector",
+ subsector_id: "Subsector",
+ economic_activity_id: "Atividade económica",
+ location_mode: "Uma ou várias localizações",
+ geographic_scope: "Âmbito geográfico",
+ multi_district_rationale: "Justificação territorial",
+ locations: "Localizações guardadas",
+ executive_summary: "Resumo executivo",
+ demand_statement: "Necessidade e proposta",
+ visibility: "Visibilidade após publicação",
+ truth_declaration: "Declaração de veracidade",
+ publication_languages: "Versões por idioma",
+ language_code: "Idioma",
+ title: "Título",
+ summary: "Resumo",
+ documents: "Documentos guardados",
+ evidences: "Evidências",
+ document_id: "Documento associado",
+ evidence_type: "Tipo de evidência",
+ description: "Descrição",
+ images: "Imagens guardadas",
+ review_due_date: "Data de revisão editorial",
+ real_estate: "Imobiliário",
+ land_rights: "DUAT e direitos fundiários",
+ business_transaction: "Negócio",
+ transaction_type: "Modalidade",
+ property_type: "Tipo de imóvel",
+ construction_status: "Estado construtivo",
+ property_condition: "Condição do imóvel",
+ land_area: "Área do terreno",
+ built_area: "Área construída",
+ area_unit: "Unidade da área",
+ units: "Unidades",
+ rooms: "Compartimentos",
+ floors: "Pisos",
+ amenities: "Comodidades",
+ utilities: "Serviços e acessos",
+ occupancy_status: "Ocupação",
+ title_type: "Tipo de título",
+ registration_number: "Número de registo",
+ encumbrances: "Ónus e restrições",
+ price: "Preço do imóvel",
+ rent: "Renda",
+ rent_periodicity: "Periodicidade",
+ deposit: "Caução",
+ valuation: "Avaliação",
+ viewing: "Visitas",
+ planning_permit_document_id: "Licença de construção",
+ use_license_document_id: "Licença de utilização",
+ operation_type: "Operação fundiária admissível",
+ duat_status: "Situação do DUAT",
+ duat_number: "Número do DUAT",
+ holder_id: "Titular cadastrado",
+ holder_name: "Nome do titular",
+ issuing_authority_id: "Entidade emissora",
+ issue_date: "Data de emissão",
+ expiry_date: "Data de validade",
+ authorized_purpose: "Finalidade autorizada",
+ exploitation_plan_document_id: "Plano de exploração",
+ parcels: "Parcelas",
+ location_id: "Localização associada",
+ area: "Área",
+ cadastral_number: "Número cadastral",
+ overlap_status: "Sobreposição",
+ improvements: "Benfeitorias",
+ communities: "Comunidades",
+ community_consultation: "Consulta comunitária",
+ overlaps_conflicts: "Sobreposições e conflitos",
+ required_authorizations: "Autorizações necessárias",
+ consideration: "Contraprestação",
+ legal_entity_id: "Entidade representada",
+ legal_form: "Forma jurídica",
+ percentage_offered: "Percentagem oferecida",
+ asking_price: "Valor solicitado",
+ financial_periods: "Exercícios financeiros",
+ assets_liabilities: "Ativos e passivos",
+ employees: "Empregos e obrigações",
+ contracts_licenses: "Contratos e licenças",
+ litigation_contingencies: "Litígios e contingências",
+ reason_for_transaction: "Fundamentação da operação",
+ partner_contribution: "Contribuição do parceiro",
+ governance_rights: "Direitos de governação",
+ franchise_terms: "Condições da franquia",
+ confidentiality_level: "Confidencialidade",
+ due_diligence_status: "Preparação da análise",
+ opportunity_type: "Tipo de investimento",
+ maturity_stage: "Etapa de maturidade",
+ investment_modalities: "Modalidades de investimento",
+ investor_profiles: "Perfis de investidor",
+ products: "Produtos",
+ assets: "Ativos",
+ inputs: "Insumos",
+ markets: "Mercados",
+ competitive_advantage: "Vantagem competitiva",
+ employment: "Emprego",
+ impact_indicators: "Impactos",
+ total_investment: "Investimento total",
+ currency: "Moeda",
+ investment_breakdown: "Rubricas de investimento",
+ secured_financing: "Financiamento assegurado",
+ funding_sought: "Financiamento procurado",
+ financial_indicators: "Indicadores financeiros",
+ milestones: "Marcos",
+ licenses: "Licenças",
+ environmental_social: "Aspetos ambientais e sociais",
+ risks: "Riscos",
+ relations: "Relações",
+ amount: "Montante",
+ name: "Nome",
+ label: "Designação",
+ status: "Estado",
+ date: "Data",
+ method: "Método",
+ appraiser: "Avaliador",
+ year: "Exercício",
+ revenue: "Receita",
+ profit: "Resultado",
+ type: "Tipo",
+ value: "Valor",
+ details: "Detalhes",
+ mitigation: "Mitigação",
+ due_date: "Prazo",
+ authority: "Entidade competente",
+ assessment_status: "Estado da avaliação",
+ environmental_category: "Categoria ambiental",
+ direct_jobs: "Empregos diretos",
+ employment_type: "Tipo de emprego",
+ geometry: "Geometria da parcela",
+ module_profile_version: "Perfil modular aprovado",
+ start_date: "Data de início",
+ end_date: "Data de fim",
+ responsible_name: "Responsável declarado",
+ dependencies: "Marcos dos quais depende",
+ scenario: "Cenário analisado",
+ npv: "Valor atual líquido",
+ irr: "Taxa interna de retorno (%)",
+ payback_years: "Prazo de retorno (anos)",
+ horizon_years: "Horizonte (anos)",
+ discount_rate: "Taxa de desconto (%)",
+ model_document_id: "Modelo financeiro associado",
+ title_holder_name: "Titular do título",
+ title_document_id: "Documento do título",
+ holder_document_id: "Documento do titular",
+ expected_completion_date: "Conclusão prevista",
+ occupancy_details: "Condições de ocupação",
+ occupancy_document_id: "Contrato de ocupação",
+ urban_limit_document_id: "Fonte do limite urbanístico",
+ max_built_area: "Área edificável máxima declarada",
+ amenities_other: "Outra comodidade",
+ communities_affected: "Existem comunidades afetadas?",
+ exploitation_plan_required: "Plano de exploração aplicável?",
+ entity_registration: "Registo e beneficiário efetivo",
+ tax_identifier: "Identificação fiscal",
+ legal_document_id: "Documento de constituição/registo",
+ beneficial_owner_document_id: "Documento do beneficiário efetivo",
+ available_financial_years: "Exercícios financeiros existentes",
+ liabilities: "Passivos",
+ cash_flow: "Fluxo de caixa",
+ excluded_assets: "Ativos excluídos",
+ guarantees: "Garantias",
+ reconciliation_document_id: "Documento de reconciliação",
+ obligations: "Obrigações",
+ labor_liabilities: "Passivos laborais",
+ transferability: "Transmissibilidade",
+ consent_document_id: "Consentimento de transmissão",
+ nda_document_id: "Acordo de confidencialidade",
+ teaser: "Resumo autorizado para publicação",
+ board: "Órgãos de gestão",
+ reserved_matters: "Matérias reservadas",
+ dividends: "Dividendos",
+ exit: "Saída",
+ deadlock: "Resolução de impasse",
+ initial_fee: "Encargo inicial",
+ royalties: "Royalties e encargos",
+ support: "Apoio",
+ exclusivity: "Exclusividade",
+ renewal: "Renovação",
+ termination: "Cessação",
+ brand_license_document_id: "Licença da marca",
+ publish_contact: "Autoriza publicar o contacto?",
+ public_contact_id: "Contacto para divulgação",
+};
+function FieldErrors({
+ path,
+ errors,
+}: {
+ path: string;
+ errors: Record;
+}) {
+ const message = errors[path];
+ return message ? (
+
+ {message}
+
+ ) : null;
+}
+function Editor({
+ name,
+ path,
+ schema,
+ value,
+ onChange,
+ options,
+ errors,
+}: {
+ name: string;
+ path: string;
+ schema: Schema;
+ value: unknown;
+ onChange: (v: unknown) => void;
+ options: CanonicalOptions;
+ errors: Record;
+}) {
+ if (schema.$ref)
+ schema = options.definitions[schema.$ref.split("/").pop()!] ?? schema;
+ const types = Array.isArray(schema.type) ? schema.type : [schema.type];
+ const label = labels[name] ?? name.replaceAll("_", " ");
+ const props = {
+ id: path,
+ "aria-invalid": !!errors[path],
+ "aria-describedby": errors[path] ? path + "-error" : undefined,
+ };
+ let input;
+ if (name === "geometry")
+ input = ;
+ else if (
+ name.endsWith("document_id") ||
+ name === "location_id" ||
+ name === "image_id"
+ ) {
+ const kind =
+ name === "location_id"
+ ? "locations"
+ : name === "image_id"
+ ? "images"
+ : "documents";
+ const rows = options.resources[kind] ?? [];
+ input = (
+ <>
+ onChange(e.target.value || null)}
+ >
+ Por indicar
+ {rows.map((r) => (
+
+ {r.payload.title ??
+ r.payload.role ??
+ r.file?.file_name ??
+ r.id}
+
+ ))}
+
+ {name === "location_id" && !!value && (
+ r.id === value),
+ )}
+ endpoint="/minhas-oportunidades/territory-geometries"
+ />
+ )}
+ >
+ );
+ } else if (name === "country_code")
+ input = (
+ onChange(e.target.value || null)}
+ >
+ Por indicar
+ {options.countries.map((c) => (
+
+ {c.name}
+
+ ))}
+
+ );
+ else if (name === "issuing_authority_id" || name === "authority_id")
+ input = (
+ onChange(e.target.value || null)}
+ >
+ Por indicar
+ {options.authorities.map((a) => (
+
+ {a.label_pt_mz}
+
+ ))}
+
+ );
+ else if (schema.enum)
+ input = (
+ onChange(e.target.value || null)}
+ >
+ Por indicar
+ {schema.enum
+ .filter((v) => v !== null)
+ .map((v) => (
+
+ {String(v).replaceAll("_", " ")}
+
+ ))}
+
+ );
+ else if (types.includes("boolean") || schema.const === true)
+ input = (
+
+ onChange(
+ e.target.value === ""
+ ? null
+ : e.target.value === "true",
+ )
+ }
+ >
+ Por indicar
+ Sim
+ Não
+
+ );
+ else if (types.includes("array")) {
+ const rows = Array.isArray(value) ? value : [];
+ let item = schema.items ?? { type: "string" };
+ if (item.$ref)
+ item = options.definitions[item.$ref.split("/").pop()!] ?? item;
+ const itemTypes = Array.isArray(item.type) ? item.type : [item.type];
+ return (
+
+ {label}
+
+ {rows.map((v, i) => (
+
+
+ onChange(
+ rows.map((r, j) => (j === i ? next : r)),
+ )
+ }
+ />
+
+ onChange(rows.filter((_, j) => j !== i))
+ }
+ >
+ Retirar linha {i + 1}
+
+
+ ))}
+
+ onChange([
+ ...rows,
+ itemTypes.includes("object")
+ ? {}
+ : itemTypes.includes("array")
+ ? []
+ : "",
+ ])
+ }
+ >
+ Adicionar linha
+
+
+ );
+ } else if (types.includes("object") || schema.properties) {
+ const fields = schema.properties ?? {};
+ const data =
+ value && typeof value === "object" && !Array.isArray(value)
+ ? (value as Data)
+ : {};
+ return (
+
+ {label}
+
+ {Object.entries(fields).map(([key, s]) => (
+ onChange({ ...data, [key]: v })}
+ />
+ ))}
+ {!Object.keys(fields).length && (
+
+ Este detalhe exige definição contratual antes da
+ submissão.
+
+ )}
+
+ );
+ } else {
+ const numeric = types.includes("number") || types.includes("integer");
+ input =
+ numeric || schema.format === "date" ? (
+
+ onChange(
+ e.target.value === ""
+ ? null
+ : numeric
+ ? Number(e.target.value)
+ : e.target.value,
+ )
+ }
+ />
+ ) : (
+
{context.context_geometry_count} limites disponíveis na
diff --git a/resources/js/lib/portal-navigation.ts b/resources/js/lib/portal-navigation.ts
index 7dd7ccc8..7fec45e1 100644
--- a/resources/js/lib/portal-navigation.ts
+++ b/resources/js/lib/portal-navigation.ts
@@ -1,3 +1,6 @@
+import type { ProfileAccess } from '@/types/profile-access';
+import type { OpportunityManagementAccess } from '@/types/opportunity-management';
+
export type PortalNavItem = {
id: string;
label: string;
@@ -10,6 +13,8 @@ export type PortalNavAccess = {
businesses?: boolean;
education?: boolean;
ai?: boolean;
+ profileAccess?: ProfileAccess | null;
+ opportunityManagement?: OpportunityManagementAccess | null;
};
const link = (id: string, label: string, href: string): PortalNavItem => ({
id,
@@ -19,6 +24,7 @@ const link = (id: string, label: string, href: string): PortalNavItem => ({
/** One route catalogue for the public shell and authenticated pages. */
export function portalNavigation(access: PortalNavAccess): PortalNavItem[] {
+ const opportunities = access.manager ? access.opportunityManagement : null;
const groups: PortalNavItem[] = [
{
id: 'explore',
@@ -124,7 +130,11 @@ export function portalNavigation(access: PortalNavAccess): PortalNavItem[] {
label: 'A minha área',
children: access.authenticated
? [
- link('dashboard', 'Painel', '/investidor'),
+ link(
+ 'dashboard',
+ opportunities ? 'Painel da gestão' : 'Painel',
+ opportunities ? '/dashboard' : '/investidor',
+ ),
link(
'profile',
'Perfil e empresas',
@@ -164,6 +174,24 @@ export function portalNavigation(access: PortalNavAccess): PortalNavItem[] {
'/management/interests',
),
link('crm', 'CRM interno', '/management/crm/leads'),
+ ...(opportunities
+ ? [
+ link(
+ 'manage-opportunities',
+ opportunities.manage.label,
+ opportunities.manage.href,
+ ),
+ ...(opportunities.installed
+ ? [
+ link(
+ 'create-opportunity',
+ opportunities.create.label,
+ opportunities.create.href,
+ ),
+ ]
+ : []),
+ ]
+ : []),
{
id: 'manage-catalogue',
label: 'Catálogo de investimento',
@@ -173,11 +201,15 @@ export function portalNavigation(access: PortalNavAccess): PortalNavItem[] {
'Sectores',
'/management/sectors',
),
- link(
- 'manage-opportunities',
- 'Oportunidades',
- '/management/opportunities',
- ),
+ ...(!opportunities
+ ? [
+ link(
+ 'manage-opportunities',
+ 'Oportunidades',
+ '/management/opportunities',
+ ),
+ ]
+ : []),
link(
'manage-projects',
'Projectos',
@@ -245,6 +277,17 @@ export function portalNavigation(access: PortalNavAccess): PortalNavItem[] {
: []),
],
});
+ if (access.authenticated && access.profileAccess) {
+ const profile = access.profileAccess;
+ groups.push({id: 'profile-opportunities', label: 'Perfil e oportunidades', children: [
+ ...(profile.mine ? [link('my-opportunities', 'Minhas oportunidades', profile.mine)] : []),
+ ...(profile.create ? [link('new-my-opportunity', 'Nova oportunidade', profile.create)] : []),
+ link('promoter-profile', profile.mine ? 'Autorizações de Promotor' : 'Solicitar perfil de Promotor', profile.request),
+ ...(!profile.mine && profile.review ? [link('profile-review', 'Revisão de oportunidades', profile.review)] : []),
+ ...(profile.audit ? [link('profile-audit', 'Auditoria de acessos', profile.audit)] : []),
+ ...(profile.administration ? [link('profile-administration', 'Gestão de perfis', profile.administration)] : []),
+ ]});
+ }
return groups;
}
diff --git a/resources/js/lib/profile-json.ts b/resources/js/lib/profile-json.ts
new file mode 100644
index 00000000..95d63f6b
--- /dev/null
+++ b/resources/js/lib/profile-json.ts
@@ -0,0 +1,38 @@
+export class ProfileValidationError extends Error {
+ constructor(
+ message: string,
+ public readonly fields: Record,
+ ) {
+ super(message);
+ }
+}
+export async function profileJson(
+ url: string,
+ data: object = {},
+ method: 'GET' | 'POST' = 'POST',
+) {
+ const cookie = document.cookie
+ .split('; ')
+ .find((c) => c.startsWith('XSRF-TOKEN='));
+ const response = await fetch(url, {
+ method,
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'X-XSRF-TOKEN': cookie ? decodeURIComponent(cookie.slice(11)) : '',
+ },
+ body: method === 'GET' ? undefined : JSON.stringify(data),
+ });
+ const result = await response.json();
+ if (!response.ok)
+ throw new ProfileValidationError(
+ result.message ?? 'A ação não foi concluída.',
+ Object.fromEntries(
+ Object.entries(result.errors ?? {}).map(([key, value]) => [
+ key,
+ Array.isArray(value) ? value.join(' ') : String(value),
+ ]),
+ ),
+ );
+ return result;
+}
diff --git a/resources/js/pages/dashboard.tsx b/resources/js/pages/dashboard.tsx
index 2743b68c..acebb828 100644
--- a/resources/js/pages/dashboard.tsx
+++ b/resources/js/pages/dashboard.tsx
@@ -1,8 +1,11 @@
+import ProfileNavigation from '@/components/profile-navigation';
import { Head, Link } from '@inertiajs/react';
import { dashboard } from '@/routes';
import type { InvestmentContext } from '@/pages/investor-path/index';
+import type { OpportunityManagementAccess } from '@/types/opportunity-management';
type Summary = {
+ canCreateOpportunity?: boolean;
requestsByStatus: Record;
publishedOpportunities: number;
draftOpportunities: number;
@@ -27,8 +30,10 @@ const card =
export default function Dashboard({
summary,
investorPath,
+ opportunityManagement,
}: {
summary: Summary | null;
+ opportunityManagement?: OpportunityManagementAccess | null;
investorPath?: {
contexts: InvestmentContext[];
current: {
@@ -45,8 +50,53 @@ export default function Dashboard({
Painel do portal
+
{summary ? (
<>
+ {opportunityManagement && (
+
+
+ Gestão de Oportunidades
+
+
+
+ {opportunityManagement.manage.label}
+
+ {opportunityManagement.installed ? (
+
+ {opportunityManagement.create.label}
+
+ ) : (
+
+ Preparar instalação da gestão de
+ rascunhos
+
+ )}
+
+
+ Os rascunhos de oportunidades não publicam o
+ dossier privado do investidor. Publicação exige
+ uma ação própria.
+
+
+ )}
Manifestações de interesse
@@ -71,7 +121,9 @@ export default function Dashboard({
- Gestão de Oportunidades
+ {opportunityManagement
+ ? 'Indicadores de oportunidades'
+ : 'Gestão de Oportunidades'}
@@ -163,12 +215,13 @@ export default function Dashboard({
aria-label="Acções rápidas"
className="flex flex-wrap gap-4"
>
-
- Criar oportunidade
-
+ {opportunityManagement?.create.label ??
+ 'Criar oportunidade'}
+ }
;
filters: {
q?: string;
+ queue?: string;
status?: string;
category?: string;
deleted?: boolean;
@@ -38,9 +45,12 @@ export default function Opportunities({
categories: string[];
sectors: { id: number; name: string }[];
geographyReviewCount: number;
+ basePath?: string;
+ canCreate?: boolean;
}) {
const form = useForm({
q: filters.q ?? '',
+ queue: filters.queue ?? '',
status: filters.status ?? '',
category: filters.category ?? '',
deleted: Boolean(filters.deleted),
@@ -48,10 +58,18 @@ export default function Opportunities({
geography_scope: filters.geography_scope ?? '',
});
return (
-
-
- Nova oportunidade
-
+
+ {canCreate && (
+
+ Nova oportunidade
+
+ )}
{geographyReviewCount} registos com âmbito por indicar;
referências existentes permanecem aceites.
@@ -72,7 +90,7 @@ export default function Opportunities({
{states[s] ?? s}: {counts[s] ?? 0}
@@ -82,9 +100,31 @@ export default function Opportunities({
className="flex flex-wrap gap-3"
onSubmit={(e) => {
e.preventDefault();
- form.get('/management/opportunities');
+ form.get(basePath);
}}
>
+ {basePath === '/minhas-oportunidades' && (
+
+ Fila
+
+ form.setData('queue', e.target.value)
+ }
+ >
+ Todas as autorizadas
+ Atribuídas a mim
+
+ Validação e pareceres
+
+
+ Preparação editorial
+
+ Recursos pendentes
+
+
+ )}
(
- {r.title ?? 'Rascunho sem título'}
+ {r.draft_title ?? r.title ?? 'Rascunho sem título'}
ID {r.id} · {r.reference} ·{' '}
@@ -174,24 +214,25 @@ export default function Opportunities({
·{' '}
{r.deleted_at
? 'Eliminado logicamente'
- : (states[r.status] ?? r.status)}
+ : (r.working_status ?? r.status) === 'published'
+ ? 'Versão disponibilizada'
+ : (states[r.working_status ?? r.status] ??
+ r.working_status ??
+ r.status)}
+ {r.publication && {r.publication.label}
}
Atualizado: {r.updated_at}
-
- Ver
-
-
- {r.deleted_at || r.status === 'archived'
- ? 'Restaurar'
- : r.status === 'draft'
- ? 'Continuar preenchimento'
- : 'Editar nova versão'}
-
+ Ver
+ {r.can_edit !== false && (
+
+ {r.deleted_at || r.status === 'archived'
+ ? 'Restaurar'
+ : r.status === 'draft'
+ ? 'Continuar preenchimento'
+ : 'Editar nova versão'}
+
+ )}
))}
diff --git a/resources/js/pages/management/opportunity-draft.tsx b/resources/js/pages/management/opportunity-draft.tsx
index 32b728e6..0c280325 100644
--- a/resources/js/pages/management/opportunity-draft.tsx
+++ b/resources/js/pages/management/opportunity-draft.tsx
@@ -1,12 +1,16 @@
-import { Link, router } from '@inertiajs/react';
+import OpportunityProfileActions from '@/components/opportunity-profile-actions';
+import OpportunityCanonicalFields, {
+ type CanonicalOptions,
+} from '@/components/opportunity-canonical-fields';
+import { Link, router, usePage } from '@inertiajs/react';
import TerritoryGeometryPreview from '@/components/territory-geometry-preview';
import { useState, useEffect } from 'react';
import {
TerritoryLevel,
type TerritoryOption,
} from '@/components/investment-territory';
-import { Management, Field, button, control } from './shared';
-type Values = Record;
+import { Management, Field, button, control, states } from './shared';
+type Values = Record;
type Entry = {
id: number;
reference: string;
@@ -51,8 +55,74 @@ export default function OpportunityDraft({
occurred_at: string;
}[];
}) {
+ const {
+ basePath = '/management/opportunities',
+ profileMode = false,
+ profileOrganization,
+ profileContext,
+ profileAccess,
+ profileActions = [],
+ canonicalOptions,
+ workflowState,
+ workflowTasks = [],
+ workflowParticipants,
+ publicationPreview,
+ publicationState,
+ auth,
+ canEditDraft = false,
+ } = usePage<{
+ basePath?: string;
+ profileMode?: boolean;
+ profileOrganization?: string | null;
+ profileActions?: string[];
+ profileContext?: Record | null;
+ profileAccess?: {
+ contexts: { organization_id: string | null; type: string }[];
+ } | null;
+ publicationPreview?: {
+ title: string;
+ summary: string;
+ description: string;
+ };
+ workflowParticipants?: {
+ publishers: { id: number; name: string }[];
+ validators: {
+ id: number;
+ name: string;
+ technical: boolean;
+ legal: boolean;
+ }[];
+ };
+ canonicalOptions?: CanonicalOptions;
+ workflowState?: string;
+ publicationState?: {
+ scope: string;
+ label: string;
+ public_catalog: boolean;
+ };
+ workflowTasks?: {
+ id: string;
+ title: string;
+ status: string;
+ assignee_user_id: number | null;
+ due_at: string | null;
+ }[];
+ auth: { user: { id: number } };
+ canEditDraft?: boolean;
+ }>().props;
const [data, setData] = useState({
...values,
+ ...(profileMode
+ ? {
+ organization_id: record
+ ? (profileOrganization ?? null)
+ : (profileAccess?.contexts[0]?.organization_id ?? null),
+ opportunity_category:
+ values.opportunity_category ??
+ profileAccess?.contexts[0]?.type ??
+ '',
+ }
+ : {}),
creation_key: crypto.randomUUID(),
});
const [busy, setBusy] = useState(false),
@@ -66,9 +136,10 @@ export default function OpportunityDraft({
const unavailable = Boolean(
record?.deleted_at || record?.status === 'archived',
);
+ const archiveAvailable = Boolean(usePage().props.opportunityManagement);
const set = (key: string, value: string) =>
setData((d) => ({ ...d, [key]: value }));
- async function send(action: 'save' | 'delete' | 'restore') {
+ async function send(action: 'save' | 'delete' | 'archive' | 'restore') {
if (busy) return;
setBusy(true);
setErrors({});
@@ -80,9 +151,9 @@ export default function OpportunityDraft({
const url =
action === 'save'
? record
- ? `/management/opportunities/${record.id}/draft`
- : '/management/opportunities/drafts'
- : `/management/opportunities/${record!.id}/lifecycle`;
+ ? `${basePath}/${record.id}/draft`
+ : `${basePath}/drafts`
+ : `${basePath}/${record!.id}/lifecycle`;
const response = await fetch(url, {
method: action === 'save' && record ? 'PUT' : 'POST',
headers: {
@@ -116,8 +187,7 @@ export default function OpportunityDraft({
}
setMessage(result.message);
if (result.etag) setToken(result.etag);
- if (!record)
- router.visit(`/management/opportunities/${result.id}/edit`);
+ if (!record) router.visit(`${basePath}/${result.id}/edit`);
else if (action !== 'save') router.reload();
} catch {
setMessage(
@@ -138,7 +208,61 @@ export default function OpportunityDraft({
: 'Nova oportunidade'
}
>
- Voltar à gestão
+
+ {profileMode ? 'Minhas oportunidades' : 'Voltar à gestão'}
+
+ {profileMode && record && readOnly && canEditDraft && (
+
+ Editar proposta privada
+
+ )}
+ {profileMode && !record && (
+
+ Organização e tipo autorizados
+ {
+ const [organization, type] =
+ e.target.value.split('|');
+ setData((d) => ({
+ ...d,
+ organization_id: organization || null,
+ opportunity_category: type,
+ }));
+ }}
+ >
+ {(profileAccess?.contexts ?? []).map((c) => (
+
+ {c.organization_id ?? 'Âmbito individual'} —{' '}
+ {c.type}
+
+ ))}
+
+
+ )}
+ {profileMode && record && (
+
+ Estado da preparação:{' '}
+ {(workflowState ?? record.status) === 'published'
+ ? 'Versão disponibilizada'
+ : (states[workflowState ?? record.status] ??
+ workflowState ??
+ record.status)}
+ . {publicationState?.label}.{' '}
+ {profileContext?.request_archive
+ ? 'Pedido de arquivo registado; aguarda decisão independente.'
+ : ''}{' '}
+ O Promotor solicita arquivo; não elimina nem restaura
+ oportunidades.
+
+ )}
Classificação de origem: {classification}. Esta classificação
não cria associações territoriais.
@@ -147,7 +271,8 @@ export default function OpportunityDraft({
Versão anterior fechada. As alterações são guardadas numa
nova versão de rascunho; a ficha publicada permanece
- intacta. Este incremento não submete, aprova ou publica.
+ intacta. Guardar não submete: use as ações do workflow para
+ revisão, aprovação e publicação independentes.
)}
Abrir versão atual
@@ -177,119 +302,153 @@ export default function OpportunityDraft({
void send('save');
}}
>
-
-
-
-
- Hierarquia do cadastro territorial existente.
- Alterar esta seleção não cria relações com
- projetos/clusters.
-
- {(
- [
- 'province_id',
- 'district_id',
- 'admin_post_id',
- 'locality_id',
- ] as const
- ).map((key, index) => (
- {
- const next = [
- ...path.slice(0, index),
- ...(value ? [value] : []),
- ];
- setPath(next);
- setData((previous) => ({
- ...previous,
- province_id: next[0]?.id ?? '',
- district_id: next[1]?.id ?? '',
- admin_post_id: next[2]?.id ?? '',
- locality_id: next[3]?.id ?? '',
- }));
- }}
+ {!profileMode && (
+
+
-
-
- set('opportunity_category', e.target.value)
- }
- >
- Por indicar
- {categories.map((c) => (
- {c}
+
+ Hierarquia do cadastro territorial existente.
+ Alterar esta seleção não cria relações com
+ projetos/clusters.
+
+ {(
+ [
+ 'province_id',
+ 'district_id',
+ 'admin_post_id',
+ 'locality_id',
+ ] as const
+ ).map((key, index) => (
+ {
+ const next = [
+ ...path.slice(0, index),
+ ...(value ? [value] : []),
+ ];
+ setPath(next);
+ setData((previous) => ({
+ ...previous,
+ province_id: next[0]?.id ?? '',
+ district_id: next[1]?.id ?? '',
+ admin_post_id: next[2]?.id ?? '',
+ locality_id: next[3]?.id ?? '',
+ }));
+ }}
+ />
))}
-
-
- {Object.entries({
- title: 'Título oficial',
- summary: 'Resumo',
- description: 'Descrição',
- promoter_name: 'Promotor',
- }).map(([key, label]) => (
-
- {key === 'description' || key === 'summary' ? (
- set(key, e.target.value)}
- />
- ) : (
- set(key, e.target.value)}
- />
- )}
+
+
+
+ set('opportunity_category', e.target.value)
+ }
+ >
+ Por indicar
+ {categories.map((c) => (
+ {c}
+ ))}
+
- ))}
-
- set('sector_id', e.target.value)}
+ {Object.entries({
+ title: 'Título oficial',
+ summary: 'Resumo',
+ description: 'Descrição',
+ promoter_name: 'Promotor',
+ }).map(([key, label]) => (
+
+ {key === 'description' || key === 'summary' ? (
+
+ set(key, e.target.value)
+ }
+ />
+ ) : (
+
+ set(key, e.target.value)
+ }
+ />
+ )}
+
+ ))}
+
+
+ set('sector_id', e.target.value)
+ }
+ >
+ Por indicar
+ {sectors.map((s) => (
+
+ {s.name}
+
+ ))}
+
+
+
- Por indicar
- {sectors.map((s) => (
-
- {s.name}
-
- ))}
-
-
-
-
- set('promoter_type', e.target.value)
- }
- >
- Por indicar
- {values.promoter_type &&
- ![
+
+ set('promoter_type', e.target.value)
+ }
+ >
+ Por indicar
+ {Boolean(values.promoter_type) &&
+ ![
+ 'public',
+ 'private',
+ 'ppp',
+ 'cooperative',
+ 'association',
+ 'community',
+ 'other',
+ ].includes(
+ String(values.promoter_type),
+ ) && (
+
+ {String(values.promoter_type)}{' '}
+ (valor existente)
+
+ )}
+ {[
'public',
'private',
'ppp',
@@ -297,174 +456,170 @@ export default function OpportunityDraft({
'association',
'community',
'other',
- ].includes(String(values.promoter_type)) && (
-
- {String(values.promoter_type)} (valor
- existente)
-
- )}
- {[
- 'public',
- 'private',
- 'ppp',
- 'cooperative',
- 'association',
- 'community',
- 'other',
- ].map((c) => (
- {c}
- ))}
-
-
-
- (
+ {c}
+ ))}
+
+
+ {
- const stage = e.target.value;
- if (stage.startsWith('legacy:')) {
- setData((d) => ({
- ...d,
- maturity_catalogue_version:
- maturityCatalogue.legacyVersion,
- maturity_level: Number(stage.slice(7)),
- maturity_stage: null,
- }));
- } else {
- setData((d) => ({
- ...d,
- maturity_catalogue_version:
- maturityCatalogue.version,
- maturity_stage: stage || null,
- maturity_level: stage
- ? Object.keys(
- maturityCatalogue.stages,
- ).indexOf(stage) + 1
- : null,
- }));
- }
- }}
>
- Por indicar
- {values.maturity_level &&
- values.maturity_catalogue_version !==
- maturityCatalogue.version && (
-
- {
- maturityCatalogue.legacyLabels[
- String(values.maturity_level)
- ]
- }{' '}
- (catálogo histórico; sem conversão)
-
+ {
+ const stage = e.target.value;
+ if (stage.startsWith('legacy:')) {
+ setData((d) => ({
+ ...d,
+ maturity_catalogue_version:
+ maturityCatalogue.legacyVersion,
+ maturity_level: Number(
+ stage.slice(7),
+ ),
+ maturity_stage: null,
+ }));
+ } else {
+ setData((d) => ({
+ ...d,
+ maturity_catalogue_version:
+ maturityCatalogue.version,
+ maturity_stage: stage || null,
+ maturity_level: stage
+ ? Object.keys(
+ maturityCatalogue.stages,
+ ).indexOf(stage) + 1
+ : null,
+ }));
+ }
+ }}
+ >
+ Por indicar
+ {Boolean(values.maturity_level) &&
+ values.maturity_catalogue_version !==
+ maturityCatalogue.version && (
+
+ {
+ maturityCatalogue.legacyLabels[
+ String(
+ values.maturity_level,
+ )
+ ]
+ }{' '}
+ (catálogo histórico; sem conversão)
+
+ )}
+ {Object.entries(maturityCatalogue.stages).map(
+ ([code, label], index) => (
+
+ {index + 1}. {label}
+
+ ),
)}
- {Object.entries(maturityCatalogue.stages).map(
- ([code, label], index) => (
-
- {index + 1}. {label}
-
- ),
- )}
-
-
- O catálogo de oito etapas é guardado com a sua
- versão. Os valores históricos conservam o
- significado anterior.
-
-
-
-
- set('financing_modality', e.target.value)
- }
- />
-
-
-
- set('expected_impact', e.target.value)
- }
- />
-
- {(data.opportunity_category === 'investment_project' ||
- (!data.opportunity_category &&
- data.estimated_investment_amount != null)) && (
- <>
-
-
- set(
- 'estimated_investment_amount',
- e.target.value,
- )
- }
- />
-
-
-
- set(
- 'estimated_investment_currency',
- e.target.value,
- )
- }
- >
- Por indicar
- {['MZN', 'USD', 'EUR', 'ZAR'].map((c) => (
- {c}
- ))}
-
-
- >
- )}
- {data.opportunity_category &&
- data.opportunity_category !== 'investment_project' && (
+
- O módulo especializado desta categoria permanece
- pendente. Pode guardar a identificação
- incompleta; não será submetida nem publicada.
+ O catálogo de oito etapas é guardado com a sua
+ versão. Os valores históricos conservam o
+ significado anterior.
+
+
+
+ set('financing_modality', e.target.value)
+ }
+ />
+
+
+
+ set('expected_impact', e.target.value)
+ }
+ />
+
+ {(data.opportunity_category === 'investment_project' ||
+ (!data.opportunity_category &&
+ data.estimated_investment_amount != null)) && (
+ <>
+
+
+ set(
+ 'estimated_investment_amount',
+ e.target.value,
+ )
+ }
+ />
+
+
+
+ set(
+ 'estimated_investment_currency',
+ e.target.value,
+ )
+ }
+ >
+ Por indicar
+ {['MZN', 'USD', 'EUR', 'ZAR'].map(
+ (c) => (
+ {c}
+ ),
+ )}
+
+
+ >
)}
-
+ {Boolean(data.opportunity_category) &&
+ data.opportunity_category !==
+ 'investment_project' && (
+
+ Guarde o rascunho incompleto e complete o
+ contrato aplicável abaixo. Submissão e
+ publicação exigem os documentos e as
+ revisões desta categoria.
+
+ )}
+
+ )}
{!readOnly && (
<>
)}
- {record && (
+ {record && !profileMode && (
<>
void send(
- unavailable ? 'restore' : 'delete',
+ unavailable
+ ? 'restore'
+ : archiveAvailable
+ ? 'archive'
+ : 'delete',
)
}
>
{unavailable
? 'Restaurar'
- : closedVersion
+ : archiveAvailable || closedVersion
? 'Arquivar'
: 'Excluir rascunho'}
+ {archiveAvailable &&
+ !unavailable &&
+ !closedVersion && (
+ void send('delete')}
+ >
+ Excluir rascunho
+
+ )}
>
)}
>
@@ -525,7 +696,7 @@ export default function OpportunityDraft({
@@ -534,11 +705,131 @@ export default function OpportunityDraft({
: 'Plano de ativação de imagens, documentos e localizações'}
)}
- {record && (
-
+ {record && !profileMode && (
+
Consultar projetos, clusters e relações existentes
)}
+ {profileMode && canonicalOptions && (
+
+
+ }
+ onChange={(v) =>
+ setData((d) => ({ ...d, canonical: v }))
+ }
+ options={canonicalOptions}
+ errors={errors}
+ category={String(data.opportunity_category ?? '')}
+ organization={
+ (data.organization_id ?? null) as string | null
+ }
+ actorId={auth.user.id}
+ sectors={sectors}
+ disabled={busy || readOnly || unavailable}
+ />
+ {!readOnly && !unavailable && (
+ void send('save')}
+ >
+ Guardar contrato no rascunho
+
+ )}
+ {Object.entries(errors)
+ .filter(([key]) => key.startsWith('canonical'))
+ .map(([key, msg]) => (
+
+ {key}: {msg}
+
+ ))}
+
+ )}
+ {profileMode && record && profileActions.includes('publish') && (
+
+ Pré-visualização da publicação
+
+ Âmbito solicitado:{' '}
+ {(data.canonical as Record | undefined)
+ ?.visibility === 'public'
+ ? 'Catálogo público, após ação do Publicador'
+ : 'Acesso restrito aos perfis e à organização autorizados'}
+
+ {publicationPreview?.title}
+ {publicationPreview?.summary}
+ {publicationPreview?.description}
+
+ A ficha partilha apenas título, resumo, proposta, sector
+ e território. Contactos, avaliações, evidências e
+ originais conservam o acesso restrito.
+
+
+ )}
+ {profileMode && record && etag && (
+ ,
+ )}
+ onErrors={setErrors}
+ id={record.id}
+ etag={token ?? etag}
+ actions={profileActions}
+ publicationVisibility={String(
+ (data.canonical as Record | undefined)
+ ?.visibility ?? 'internal',
+ )}
+ gates={canonicalOptions?.gates ?? []}
+ documents={(
+ canonicalOptions?.resources.documents ?? []
+ ).map((d) => ({
+ id: d.id,
+ title: d.payload.title ?? d.file?.file_name ?? d.id,
+ }))}
+ approvalHash={
+ (
+ profileContext?.approval as
+ | { hash?: string }
+ | undefined
+ )?.hash
+ }
+ />
+ )}
+ {profileMode && record && (
+
+
+ Acompanhamento interno —{' '}
+ {(workflowState ?? record.status) === 'published'
+ ? 'Versão disponibilizada'
+ : (states[workflowState ?? record.status] ??
+ workflowState ??
+ record.status)}
+
+
+ SLA: sem política/prazo aprovado; as tarefas podem ser
+ preparadas em paralelo.
+
+ {workflowTasks.map((t) => (
+
+ {t.title} — {t.status}; responsável:{' '}
+ {t.assignee_user_id ?? 'por atribuir'}; prazo:{' '}
+ {t.due_at ?? 'não definido'}
+
+ ))}
+
+ )}
Histórico
{history.length ? (
diff --git a/resources/js/pages/management/opportunity-resources.tsx b/resources/js/pages/management/opportunity-resources.tsx
index 7cc975d4..46b5f3a0 100644
--- a/resources/js/pages/management/opportunity-resources.tsx
+++ b/resources/js/pages/management/opportunity-resources.tsx
@@ -1,4 +1,4 @@
-import { Link, router } from '@inertiajs/react';
+import { Link, router, usePage } from '@inertiajs/react';
import TerritoryGeometryPreview from '@/components/territory-geometry-preview';
import { useState } from 'react';
import {
@@ -144,9 +144,10 @@ export default function OpportunityResources({
assessment: string[];
imageProcessingAvailable: boolean;
}) {
+ const { basePath = '/management/opportunities', readOnly = false, countries = [] } = usePage<{basePath?: string; readOnly?: boolean; countries?: {code:string;name:string}[]}>().props;
const [kind, setKind] = useState('locations');
const [editing, setEditing] = useState(null);
- const [payload, setPayload] = useState({});
+ const [payload, setPayload] = useState({country_code:'MZ'});
const [path, setPath] = useState([]);
const [geometry, setGeometry] = useState('');
const [file, setFile] = useState(null);
@@ -161,7 +162,7 @@ export default function OpportunityResources({
function select(nextKind: Kind, record: Resource | null = null) {
setKind(nextKind);
setEditing(record);
- setPayload(record?.payload ?? {});
+ setPayload(record?.payload ?? (nextKind === 'locations' ? {country_code:'MZ'} : {}));
setPath(record?.territoryPath ?? []);
setGeometry(
record?.payload.geometry
@@ -174,7 +175,7 @@ export default function OpportunityResources({
setErrors({});
}
async function execute(action: 'save' | 'delete' | 'restore' | 'prepare') {
- if (busy) return;
+ if (busy || readOnly) return;
setBusy(true);
setErrors({});
setMessage('');
@@ -204,7 +205,7 @@ export default function OpportunityResources({
form.set('action', action);
form.set('confirm', confirm ? '1' : '0');
}
- const url = `/management/opportunities/${opportunity.id}/resources/${kind}${editing ? `/${editing.id}` : ''}${action === 'save' ? '' : action === 'prepare' ? '/prepare' : '/lifecycle'}`;
+ const url = `${basePath}/${opportunity.id}/resources/${kind}${editing ? `/${editing.id}` : ''}${action === 'save' ? '' : action === 'prepare' ? '/prepare' : '/lifecycle'}`;
const csrf =
document.cookie
.split('; ')
@@ -266,7 +267,7 @@ export default function OpportunityResources({
!!opportunity.deleted_at || opportunity.status === 'archived';
return (
-
+
Regressar ao rascunho #{opportunity.id}
@@ -327,7 +328,7 @@ export default function OpportunityResources({
select(k)}
>
{k === 'locations'
@@ -388,7 +389,7 @@ export default function OpportunityResources({
{r.file?.malware_scan_status === 'clean' &&
!r.deleted_at && (
Consultar original autorizado
@@ -410,9 +411,12 @@ export default function OpportunityResources({
{kind === 'locations' && (
+
set('country_code',e.target.value)}>Por indicar {countries.map(c=>{c.name} )}
+ {payload.country_code !== 'MZ' &&
A hierarquia abaixo corresponde a Moçambique. Uma localização noutro país requer o seu próprio cadastro; não use territórios moçambicanos para a representar.
}
{[0, 1, 2, 3].map((index) => (
setPath((previous) =>
value
@@ -638,7 +643,7 @@ export default function OpportunityResources({
type="button"
className={button}
disabled={
- busy || unavailable || !imageProcessingAvailable
+ busy || readOnly || unavailable || !imageProcessingAvailable
}
onClick={() => void execute('prepare')}
>
@@ -647,7 +652,7 @@ export default function OpportunityResources({
)}
Guardar recurso
@@ -655,7 +660,7 @@ export default function OpportunityResources({
void execute(
editing.deleted_at ? 'restore' : 'delete',
diff --git a/resources/js/pages/management/shared.tsx b/resources/js/pages/management/shared.tsx
index 407a0a38..6c2245ee 100644
--- a/resources/js/pages/management/shared.tsx
+++ b/resources/js/pages/management/shared.tsx
@@ -1,3 +1,4 @@
+import ProfileNavigation from '@/components/profile-navigation';
import { Head, Link, usePage } from '@inertiajs/react';
import type { ReactNode } from 'react';
import { cloneElement, isValidElement, useId } from 'react';
@@ -46,7 +47,9 @@ export function Management({
title: string;
children: ReactNode;
}) {
- const { flash, educationEnabled, aiEnabled } = usePage<{
+ const { flash, educationEnabled, aiEnabled, auth, basePath } = usePage<{
+ auth?: {canManagePortal?: boolean};
+ basePath?: string;
flash?: { success?: string };
educationEnabled?: boolean;
aiEnabled?: boolean;
@@ -54,7 +57,7 @@ export function Management({
return (
-
@@ -102,7 +105,7 @@ export function Management({
Referências e formulários
Portal público
-
+ : }
{title}
{flash?.success && (
Exemplar INE de 07/06/2019 aceite. Correspondência exata de nome
- e pai; sem alterações de classificações territoriais,
+ e pai, ou correspondência explícita fundamentada abaixo;
+ sem alterações de classificações territoriais,
disponibilidade fundiária ou cálculos.
@@ -105,6 +108,12 @@ export default function GeometryImport({ plan }: { plan: Plan }) {
SHA-256 do original: {plan.source_sha256}
+ Versão das correspondências: {plan.correspondence_version}.
+ {
+ setApplyKey(crypto.randomUUID());
+ setConfirmed(false);
+ router.reload({ only: ["plan"] });
+ }}>Atualizar pré-visualização
@@ -113,6 +122,7 @@ export default function GeometryImport({ plan }: { plan: Plan }) {
Nome
Pai
Correspondência
+ Fundamento
Ação prevista
@@ -123,6 +133,10 @@ export default function GeometryImport({ plan }: { plan: Plan }) {
{r.name}
{r.parent_name ?? "—"}
{r.location_id ?? "Pendente"}
+ {r.correspondence ? <>
+ {r.correspondence.target_name} (código {r.correspondence.target_source_code})
+ {r.correspondence.basis}
+ > : "Nome único sob o pai correspondido"}
{r.status}
))}
diff --git a/resources/js/pages/profiles/administration.tsx b/resources/js/pages/profiles/administration.tsx
new file mode 100644
index 00000000..1b1fd2d3
--- /dev/null
+++ b/resources/js/pages/profiles/administration.tsx
@@ -0,0 +1,76 @@
+import { Head, Link, router } from '@inertiajs/react';
+import { useState } from 'react';
+import ProfileNavigation from '@/components/profile-navigation';
+import { profileJson } from '@/lib/profile-json';
+import { button, control } from '@/pages/management/shared';
+
+type Entry = {id: string; user_id: number; status: string; version: number; opportunity_types: string; document_ids: string; reason: string};
+type SecurityEntry = {id: string; kind: string; requested_by: number; subject_user_id: number; scope: string; reason: string; approved_by: number | null; consumed_at: string | null; expires_at: string};
+type Pair = {first_user_id: number; second_user_id: number; version: number};
+function Grant({types, organizations}: {types: string[]; organizations: {id: string; name: string}[]}) {
+ const [user, setUser] = useState(''); const [role, setRole] = useState('validator'); const [organization, setOrganization] = useState('');
+ const [selected, setSelected] = useState([]); const [responsibilities, setResponsibilities] = useState([]);
+ const [reason, setReason] = useState(''); const [expires, setExpires] = useState(''); const [message, setMessage] = useState(''); const [busy, setBusy] = useState(false);
+ const available = role === 'validator' ? ['validation_coordinator','technical_reviewer','legal_reviewer','appeal_reviewer'] : role === 'publisher' ? ['publication_coordinator'] : [];
+ const toggle = (values: string[], value: string) => values.includes(value) ? values.filter(v => v !== value) : [...values,value];
+ async function send() { setBusy(true); try { await profileJson('/perfis/atribuicoes', {user_id: Number(user), role, organization_id: organization || null, opportunity_types: selected, responsibilities, expires_at: expires || null, reason}); setMessage('Atribuição registada.'); router.reload(); } catch(error) {setMessage(error instanceof Error ? error.message : 'Resposta indisponível.');} finally {setBusy(false);} }
+ return ;
+}
+function Security({pair, entries, actorId}: {pair: Pair; entries: SecurityEntry[]; actorId: number}) {
+ const [old, setOld] = useState(String(pair.second_user_id)); const [candidate, setCandidate] = useState(''); const [reason, setReason] = useState('');
+ const [action, setAction] = useState('edit'); const [record, setRecord] = useState(''); const [message, setMessage] = useState(''); const [busy, setBusy] = useState(false);
+ async function send(path: string, data: object) {setBusy(true); try {const result = await profileJson(path, data); setMessage(result.message ?? `Pedido registado: ${result.id}`); router.reload();} catch(error) {setMessage(error instanceof Error ? error.message : 'Resposta indisponível.');} finally {setBusy(false);}}
+ return Operações críticas
+ Fundamento setReason(e.target.value)} />
+ {e.preventDefault(); void send('/perfis/substituicoes', {old_user_id: Number(old), new_user_id: Number(candidate), reason});}}>
+ Titular a substituir setOld(e.target.value)}>{[pair.first_user_id,pair.second_user_id].map(v => {v} )}
+ ID do candidato com MFA confirmado setCandidate(e.target.value)} /> Preparar substituição atómica
+
+ {e.preventDefault(); void send('/perfis/elevacoes', {action, record_id: record ? Number(record) : null, reason});}}>
+ Operação a elevar setAction(e.target.value)}>{['create','edit','validate','publish','archive'].map(v => {v} )}
+ ID da oportunidade setRecord(e.target.value)} /> Pedir elevação temporária Exige aprovação do outro titular e papel operacional válido. Não remove impedimentos de autoria ou Auditor.
+
+ {entries.map(entry => {entry.kind} — {entry.id} — solicitante {entry.requested_by}, destinatário {entry.subject_user_id}
{entry.reason}; validade: {entry.expires_at}
Âmbito: {entry.scope}
+ {!entry.consumed_at && !entry.approved_by && entry.requested_by !== actorId && entry.subject_user_id !== actorId && void send(`/perfis/seguranca/${entry.id}/aprovar`, {})}>Aprovar independentemente }
+ {!entry.consumed_at && entry.approved_by && entry.requested_by === actorId && entry.kind === 'replacement' && void send(`/perfis/substituicoes/${entry.id}/aplicar`, {})}>Aplicar substituição aprovada }
+ {entry.consumed_at ? 'Aplicado' : entry.approved_by ? `Aprovado pela conta ${entry.approved_by}` : 'Aguarda aprovação independente'}
+ )}{message}
;
+}
+function Decision({ entry }: {entry: Entry}) {
+ const [reason, setReason] = useState(''); const [verified, setVerified] = useState(false); const [message, setMessage] = useState(''); const [busy, setBusy] = useState(false);
+ const types: string[] = JSON.parse(entry.opportunity_types);
+ const [approved, setApproved] = useState([]);
+ async function send(decision: string) {
+ setBusy(true); try { await profileJson(`/perfis/pedidos/${entry.id}/decisao`, {version: entry.version, decision, reason, approved_types: approved,
+ verified_identity: verified, verified_representation: verified, verified_documents: verified}); router.reload(); }
+ catch(error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível.'); } finally { setBusy(false); }
+ }
+ return Pedido {entry.id} — conta {entry.user_id} — {entry.status} {entry.reason}
Comprovativos canónicos: {(JSON.parse(entry.document_ids) as string[]).map(id => Consultar {id})}
+ {entry.status === 'pending' && <>Tipos efetivamente aprovados {types.map(type => setApproved(v => v.includes(type) ? v.filter(x => x !== type) : [...v,type])} /> {type} )}
+ setVerified(e.target.checked)} /> Conferi identidade, representação e comprovativos; esta declaração fica auditada.
+ Fundamento setReason(e.target.value)} />
+ void send('approved')}>Aprovar tipos selecionados void send('rejected')}>Rejeitar pedido >}
+ {message}
;
+}
+export default function Administration({requests, pair, assignments, securityAlerts, actorId, types, organizations, securityRequests}: {actorId: number; types: string[]; organizations: {id: string; name: string}[]; securityRequests: SecurityEntry[]; securityAlerts: {id: string; action: string; actor_user_id: number; occurred_at: string}[]; requests: Entry[]; pair: Pair; assignments: {id: string; user_id: number; role: string; revoked_at: string | null}[]}) {
+ const [message, setMessage] = useState(''); const [reason, setReason] = useState('');
+ async function revoke(id: string) { try { await profileJson(`/perfis/atribuicoes/${id}/revogar`, {reason}); router.reload(); } catch(error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível.'); } }
+ return Gestão de perfis
+ Dupla de superutilizadores: contas {pair.first_user_id} e {pair.second_user_id}; versão {pair.version}. Substituição exige operação atómica e aprovação independente. Não há remoção isolada.
+ Alertas de segurança {securityAlerts.map(a => {a.occurred_at}: {a.action} — conta {a.actor_user_id}
)}
+ Pedidos de Promotor {requests.map(r => )}
+
+ Atribuições e revogação Motivo de revogação setReason(e.target.value)} />
+ {assignments.map(a => Conta {a.user_id}: {a.role} — {a.revoked_at ? 'revogado' : 'atribuído'} {!a.revoked_at && void revoke(a.id)}>Revogar e invalidar sessões }
)}{message}
+ ;
+}
diff --git a/resources/js/pages/profiles/audit.tsx b/resources/js/pages/profiles/audit.tsx
new file mode 100644
index 00000000..69eb08e2
--- /dev/null
+++ b/resources/js/pages/profiles/audit.tsx
@@ -0,0 +1,21 @@
+import { Head, useForm } from '@inertiajs/react';
+import ProfileNavigation from '@/components/profile-navigation';
+import { button, control, Pagination, type Paginated } from '@/pages/management/shared';
+
+type Event = {id: string; action: string; actor_user_id: number | null; entity_type: string; source_system: string; occurred_at: string};
+export default function Audit({records, filters}: {records: Paginated; filters: Record}) {
+ const form = useForm({actor_id: filters.actor_id ?? '', action: filters.action ?? '', record_id: filters.record_id ?? '', from: filters.from ?? '', until: filters.until ?? ''});
+ const search = new URLSearchParams(Object.entries(form.data).filter(([,value]) => value !== ''));
+ search.set('format', 'json');
+ return Auditoria de acessos e decisões
+ Consulta somente de leitura. A exportação contém metadados; não inclui credenciais, documentos nem snapshots privados decifrados. Cada exportação apresenta o limite aplicado.
+ {e.preventDefault(); form.get('/perfis/auditoria');}}>
+ {(['actor_id','action','record_id','from','until'] as const).map(field => {field} form.setData(field,e.target.value)} /> )}
+ Filtrar
+
+ {Object.values(form.errors).map(error => {error}
)}
+ Exportar metadados JSON, até 1.000 eventos
+ Data UTC Conta Ação Recurso Origem {records.data.map(e => {e.occurred_at} {e.actor_user_id} {e.action} {e.entity_type} {e.source_system} )}
+ {!records.data.length && Nenhum evento corresponde aos filtros.
}
+ ;
+}
diff --git a/resources/js/pages/profiles/installation.tsx b/resources/js/pages/profiles/installation.tsx
new file mode 100644
index 00000000..34a97a5e
--- /dev/null
+++ b/resources/js/pages/profiles/installation.tsx
@@ -0,0 +1,194 @@
+import { useState } from 'react';
+import { Management, button, control } from '@/pages/management/shared';
+import { profileJson } from '@/lib/profile-json';
+
+type Plan = {
+ installed: boolean;
+ consistent: boolean;
+ ready: boolean;
+ target: { database: string; port: number };
+ hash: string;
+ dependencies: Record;
+ changes: string[];
+ backupDate: string | null;
+ rollback: string;
+ bootstrap: {
+ initialized: boolean;
+ holders: number[];
+ version: number | null;
+ rule: string;
+ };
+};
+export default function Installation(initial: Plan) {
+ const [plan, setPlan] = useState(initial);
+ const [reason, setReason] = useState('');
+ const [confirmed, setConfirmed] = useState(false);
+ const [first, setFirst] = useState('');
+ const [second, setSecond] = useState('');
+ const [busy, setBusy] = useState(false);
+ const [message, setMessage] = useState('');
+ async function run(bootstrap = false) {
+ setBusy(true);
+ setMessage('');
+ try {
+ const result = await profileJson(
+ '/management/profile-install' + (bootstrap ? '/bootstrap' : ''),
+ {
+ hash: plan.hash,
+ confirm: confirmed,
+ reason,
+ idempotency_key: crypto.randomUUID(),
+ ...(bootstrap
+ ? {
+ first_user_id: Number(first),
+ second_user_id: Number(second),
+ }
+ : {}),
+ },
+ );
+ setMessage(
+ bootstrap
+ ? 'Dupla inicializada. Inicie uma nova sessão como um dos titulares designados; MFA permanece obrigatório.'
+ : result.changed
+ ? 'Schema instalado. Perfis ainda não disponibilizados; nenhuma conta ou atribuição criada.'
+ : 'Schema já instalado. Nenhuma reinstalação ou duplicação.',
+ );
+ if (!bootstrap)
+ setPlan(
+ (await profileJson(
+ '/management/profile-install',
+ {},
+ 'GET',
+ )) as Plan,
+ );
+ setConfirmed(false);
+ } catch (error) {
+ setMessage(
+ error instanceof Error
+ ? error.message
+ : 'Resposta indisponível; consulte o estado antes de repetir.',
+ );
+ } finally {
+ setBusy(false);
+ }
+ }
+ return (
+
+
+ Base {plan.target.database}:{plan.target.port} ·{' '}
+ {plan.installed ? 'Schema instalado' : 'Schema por instalar'}
+
+
+ Preparação:{' '}
+ {plan.ready
+ ? 'Provas atuais verificadas'
+ : 'Dependências ou provas por completar'}
+ . Preparação não significa instalação ou disponibilização dos
+ perfis.
+
+ {!plan.consistent && (
+
+ Ledger e schema divergem. Recuperar a consistência antes de
+ instalar.
+
+ )}
+
+ {Object.entries(plan.dependencies).map(([key, ok]) => (
+
+ {key}: {ok ? 'presente' : 'pendente'}
+
+ ))}
+
+
+ {plan.changes.map((c) => (
+ {c}
+ ))}
+
+ Backup/restauro: {plan.backupDate ?? 'Prova atual pendente'}
+ {plan.rollback}
+
+ Fundamento
+ setReason(e.target.value)}
+ />
+
+
+ setConfirmed(e.target.checked)}
+ />{' '}
+ Confirmo exclusivamente a ação indicada nesta base
+
+ void run()}
+ >
+ Instalar schema 040000
+
+
+ {message}
+
+ );
+}
diff --git a/resources/js/pages/profiles/request.tsx b/resources/js/pages/profiles/request.tsx
new file mode 100644
index 00000000..a07e460b
--- /dev/null
+++ b/resources/js/pages/profiles/request.tsx
@@ -0,0 +1,48 @@
+import { Head, Link, router } from '@inertiajs/react';
+import { useState } from 'react';
+import ProfileNavigation from '@/components/profile-navigation';
+import { profileJson } from '@/lib/profile-json';
+import { button, control } from '@/pages/management/shared';
+
+type RequestEntry = { id: string; status: string; reason: string; decision_reason: string | null; created_at: string };
+export default function RequestProfile({ requests, types, organizations, documents }: {
+ requests: RequestEntry[]; types: string[]; organizations: {id: string; name: string}[]; documents: {id: string; file_name: string}[];
+}) {
+ const [representation, setRepresentation] = useState('individual');
+ const [organization, setOrganization] = useState('');
+ const [selected, setSelected] = useState([]);
+ const [proofs, setProofs] = useState([]);
+ const [reason, setReason] = useState('');
+ const [key, setKey] = useState(() => crypto.randomUUID());
+ const [message, setMessage] = useState('');
+ const [busy, setBusy] = useState(false);
+ async function send() {
+ setBusy(true); setMessage('');
+ try {
+ const result = await profileJson('/perfil/promotor', { creation_key: key, representation_type: representation, organization_id: representation === 'individual' ? null : organization,
+ opportunity_types: selected, document_ids: proofs, reason });
+ setMessage(result.message); setKey(crypto.randomUUID()); router.reload();
+ } catch (error) { setMessage(error instanceof Error ? error.message : 'Resposta indisponível. Confira o acompanhamento antes de repetir.'); }
+ finally { setBusy(false); }
+ }
+ const toggle = (values: string[], id: string) => values.includes(id) ? values.filter(v => v !== id) : [...values, id];
+ return
+ Solicitar perfil de Promotor
+ A aprovação confirma identidade, representação e comprovativos. Só os tipos aprovados ficam disponíveis; o pedido não ativa o perfil.
+ { e.preventDefault(); void send(); }}>
+ Representação setRepresentation(e.target.value)}>
+ {['individual','company','public_entity','association','partner'].map(v => {v} )}
+
+ {representation !== 'individual' && Organização representada setOrganization(e.target.value)}>
+ Selecionar {organizations.map(o => {o.name} )}
+ }
+ Tipos pretendidos {types.map(type => setSelected(toggle(selected,type))} /> {type} )}
+ Comprovativos próprios analisados {documents.map(d => setProofs(toggle(proofs,d.id))} /> {d.file_name} )}
+ {!documents.length && Sem comprovativos próprios disponíveis. Pode anexar ao seu dossier no Balcão; o ficheiro precisa de análise antimalware concluída.
}
+ Fundamentação setReason(e.target.value)} />
+ Submeter pedido de perfil
+
+ {message}
+ Acompanhamento dos meus pedidos {requests.map(r => {r.id} — {r.status}
{r.decision_reason ?? 'Aguarda revisão independente.'}
)}{!requests.length && Nenhum pedido recebido.
}
+ ;
+}
diff --git a/resources/js/types/opportunity-management.ts b/resources/js/types/opportunity-management.ts
new file mode 100644
index 00000000..ddf40c2e
--- /dev/null
+++ b/resources/js/types/opportunity-management.ts
@@ -0,0 +1,6 @@
+export type OpportunityManagementAccess = {
+ installed: boolean;
+ manage: { label: string; href: string };
+ create: { label: string; href: string };
+ installationHref: string;
+};
diff --git a/resources/js/types/profile-access.ts b/resources/js/types/profile-access.ts
new file mode 100644
index 00000000..42063cb3
--- /dev/null
+++ b/resources/js/types/profile-access.ts
@@ -0,0 +1,9 @@
+export type ProfileAccess = {
+ contexts: { organization_id: string | null; type: string }[];
+ mine: string | null;
+ create: string | null;
+ request: string;
+ review: string | null;
+ audit?: string | null;
+ administration: string | null;
+};
diff --git a/routes/web.php b/routes/web.php
index dc92550d..a0455427 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -26,6 +26,7 @@ use App\Http\Controllers\OpportunityManagementController;
use App\Http\Controllers\OpportunityOriginReviewController;
use App\Http\Controllers\OpportunityResourceController;
use App\Http\Controllers\PortalManagementController;
+use App\Http\Controllers\PortalProfileController;
use App\Http\Controllers\PortalServicesController;
use App\Http\Controllers\PublicBusinessOpportunityController;
use App\Http\Controllers\PublicGeographyController;
@@ -33,6 +34,7 @@ use App\Http\Controllers\PublicPortalController;
use App\Http\Controllers\TerritoryGeometryImportController;
use App\Http\Middleware\AiEnabled;
use App\Http\Middleware\EducationEnabled;
+use App\Http\Middleware\EnsurePortalProfiles;
use App\Http\Middleware\RequireZoneMfa;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
@@ -108,6 +110,46 @@ Route::middleware(['auth', 'verified', 'can:manage-portal', AiEnabled::class])->
Route::get('/api/v1/investment/territory-options', [PublicGeographyController::class, 'options'])->middleware('throttle:api');
Route::get('/api/v1/investment/territory-geometries', [InvestmentTerritoryController::class, 'geometries'])->middleware('throttle:api');
+// Installation must be reachable before the profile schema/feature is enabled.
+Route::middleware(['auth', 'verified'])->group(function () {
+ Route::get('/management/profile-install', [\App\Http\Controllers\PortalProfileInstallationController::class, 'preview']);
+ Route::post('/management/profile-install', [\App\Http\Controllers\PortalProfileInstallationController::class, 'apply']);
+ Route::post('/management/profile-install/bootstrap', [\App\Http\Controllers\PortalProfileInstallationController::class, 'bootstrap']);
+});
+
+Route::middleware(['auth', 'verified', EnsurePortalProfiles::class])->group(function () {
+ $profiles = PortalProfileController::class;
+ Route::get('/perfil/promotor', [$profiles, 'requests']);
+ Route::post('/perfil/promotor', [$profiles, 'requestProfile']);
+ Route::get('/perfil/promotor/{id}', [$profiles, 'requestStatus'])->whereUuid('id');
+ Route::get('/perfis/gestao', [$profiles, 'administration']);
+ Route::get('/perfis/auditoria', [$profiles, 'audit']);
+ Route::post('/perfis/pedidos/{id}/decisao', [$profiles, 'decide'])->whereUuid('id');
+ Route::get('/perfis/pedidos/{id}/documentos/{documentId}', [$profiles, 'requestDocument'])->whereUuid(['id', 'documentId']);
+ Route::post('/perfis/atribuicoes', [$profiles, 'grant']);
+ Route::post('/perfis/atribuicoes/{id}/revogar', [$profiles, 'revoke'])->whereUuid('id');
+ Route::post('/perfis/substituicoes', [$profiles, 'replacement']);
+ Route::post('/perfis/seguranca/{id}/aprovar', [$profiles, 'approveSecurity'])->whereUuid('id');
+ Route::post('/perfis/substituicoes/{id}/aplicar', [$profiles, 'replace'])->whereUuid('id');
+ Route::post('/perfis/elevacoes', [$profiles, 'elevation']);
+ Route::get('/minhas-oportunidades', [$profiles, 'opportunities']);
+ Route::get('/minhas-oportunidades/territory-options', [InvestmentTerritoryController::class, 'options']);
+ Route::get('/minhas-oportunidades/territory-geometries', [InvestmentTerritoryController::class, 'geometries']);
+ Route::get('/minhas-oportunidades/create', [$profiles, 'edit']);
+ Route::get('/minhas-oportunidades/{id}/edit', [$profiles, 'edit'])->whereNumber('id');
+ Route::get('/minhas-oportunidades/{id}/view', [$profiles, 'edit'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/drafts', [OpportunityManagementController::class, 'save']);
+ Route::put('/minhas-oportunidades/{id}/draft', [OpportunityManagementController::class, 'save'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/{id}/workflow', [$profiles, 'workflow'])->whereNumber('id');
+ Route::get('/minhas-oportunidades/{id}/resources', [OpportunityResourceController::class, 'index'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/{id}/resources/{kind}', [OpportunityResourceController::class, 'save'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/{id}/resources/{kind}/{resourceId}', [OpportunityResourceController::class, 'save'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/{id}/resources/{kind}/{resourceId}/lifecycle', [OpportunityResourceController::class, 'lifecycle'])->whereNumber('id');
+ Route::post('/minhas-oportunidades/{id}/resources/images/{resourceId}/prepare', [OpportunityResourceController::class, 'prepareImage'])->whereNumber('id');
+ Route::get('/minhas-oportunidades/{id}/resources/{kind}/{resourceId}/download', [OpportunityResourceController::class, 'download'])->whereNumber('id');
+ Route::get('/minhas-oportunidades/{id}/resources/images/{resourceId}/preview/{documentId}', [OpportunityResourceController::class, 'previewImage'])->whereNumber('id')->middleware('signed')->name('promoter.opportunity-image-preview');
+});
+
Route::middleware(['auth', 'verified', 'can:manage-portal'])->prefix('management')->name('management.')->group(function () {
Route::get('territory-geometry-import', [TerritoryGeometryImportController::class, 'preview']);
Route::post('territory-geometry-import', [TerritoryGeometryImportController::class, 'apply'])->middleware(RequireZoneMfa::class);
diff --git a/tests/Feature/DashboardOpportunityAccessTest.php b/tests/Feature/DashboardOpportunityAccessTest.php
new file mode 100644
index 00000000..20f9758e
--- /dev/null
+++ b/tests/Feature/DashboardOpportunityAccessTest.php
@@ -0,0 +1,76 @@
+create();
+ config(['portal.managers' => [$manager->email], 'portal.opportunity_dashboard_access_enabled' => true]);
+ $this->actingAs($manager)->get('/dashboard')->assertOk()->assertInertia(fn (Assert $page) => $page
+ ->component('dashboard')->where('auth.canManagePortal', true)
+ ->where('opportunityManagement.installed', true)
+ ->where('opportunityManagement.manage.label', 'Gestão de Oportunidades')
+ ->where('opportunityManagement.create.label', 'Nova oportunidade'));
+ // Discover destinations from the dashboard response, rather than assuming
+ // a successful direct request proves dashboard navigation.
+ $dashboard = $this->get('/dashboard')->viewData('page')['props']['opportunityManagement'];
+ $this->get($dashboard['manage']['href'])->assertInertia(fn (Assert $page) => $page->component('management/opportunities'));
+ $this->get($dashboard['create']['href'])->assertInertia(fn (Assert $page) => $page->component('management/opportunity-draft')->where('record', null));
+ $draft = $this->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid(), 'title' => 'QA dashboard draft', 'reason' => 'Criação de rascunho pelo painel de gestão QA'])->assertCreated()->json();
+ $id = $draft['id'];
+ $this->get('/management/opportunities/'.$id.'/edit')->assertInertia(fn (Assert $page) => $page->where('values.title', 'QA dashboard draft'));
+ $update = $this->putJson('/management/opportunities/'.$id.'/draft', ['etag' => $draft['etag'], 'title' => 'QA dashboard edited', 'reason' => 'Edição e recuperação autorizadas no ensaio QA'])->assertOk()->json();
+ $request = ['etag' => $update['etag'], 'action' => 'archive', 'reason' => 'Arquivo explícito sem eliminar o rascunho QA', 'confirm' => true];
+ $this->postJson('/management/opportunities/'.$id.'/lifecycle', [...$request, 'confirm' => false])->assertUnprocessable();
+ $this->postJson('/management/opportunities/'.$id.'/lifecycle', $request)->assertOk();
+ $this->assertDatabaseHas('opportunities', ['id' => $id, 'status' => 'archived', 'title' => 'QA dashboard edited', 'deleted_at' => null, 'first_submitted_at' => null, 'management_closed_once' => false]);
+ $this->get($dashboard['manage']['href'].'?status=archived')->assertInertia(fn (Assert $page) => $page->where('records.data.0.id', $id));
+ $this->putJson('/management/opportunities/'.$id.'/draft', ['etag' => $update['etag'], 'reason' => $request['reason']])->assertConflict();
+ $this->postJson('/management/opportunities/'.$id.'/lifecycle', [...$request, 'action' => 'restore', 'etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id))])->assertOk();
+ $this->get('/management/opportunities/'.$id.'/edit')->assertInertia(fn (Assert $page) => $page->where('record.status', 'draft')->where('values.title', 'QA dashboard edited'));
+ $this->assertSame(0, Opportunity::published()->count());
+ $this->assertSame(4, DB::table('audit_events')->where('source_system', 'opportunity-management')->where('after_data->record_id', $id)->count());
+ }
+
+ public function test_investor_unverified_manager_and_guest_do_not_gain_management_access(): void
+ {
+ $manager = User::factory()->unverified()->create();
+ $investor = User::factory()->create();
+ config(['portal.managers' => [$manager->email], 'portal.opportunity_dashboard_access_enabled' => true]);
+ $this->actingAs($investor)->get('/dashboard')->assertInertia(fn (Assert $page) => $page->where('summary', null)->where('opportunityManagement', null)->where('auth.canManagePortal', false));
+ $this->get('/management/opportunities')->assertForbidden();
+ $this->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid()])->assertForbidden();
+ $this->actingAs($manager)->get('/dashboard')->assertRedirect('/email/verify');
+ $this->getJson('/management/opportunities')->assertForbidden();
+ $this->assertSame(0, Opportunity::count());
+ auth()->forgetGuards();
+ $this->flushSession();
+ $this->get('/dashboard')->assertRedirect('/login');
+ }
+
+ public function test_missing_installation_is_explicit_and_disabled_increment_preserves_compatibility(): void
+ {
+ $manager = User::factory()->create();
+ config(['portal.managers' => [$manager->email], 'portal.opportunity_dashboard_access_enabled' => false]);
+ $this->actingAs($manager)->get('/dashboard')->assertInertia(fn (Assert $page) => $page->where('opportunityManagement', null));
+ $this->postJson('/management/opportunities/1/lifecycle', ['etag' => str_repeat('a', 64), 'action' => 'archive', 'reason' => 'Incremento ainda não disponibilizado nesta configuração', 'confirm' => true])->assertUnprocessable();
+ config(['portal.opportunity_dashboard_access_enabled' => true]);
+ $migration = require database_path('migrations/2026_10_09_020000_extend_opportunity_management.php');
+ $migration->down();
+ $this->get('/dashboard')->assertInertia(fn (Assert $page) => $page->where('opportunityManagement.installed', false)->where('opportunityManagement.installationHref', '/management/opportunity-management-install'));
+ $this->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid()])->assertServiceUnavailable();
+ }
+}
diff --git a/tests/Feature/ImportDocumentBatchTest.php b/tests/Feature/ImportDocumentBatchTest.php
index 328e7f58..7f257ed3 100644
--- a/tests/Feature/ImportDocumentBatchTest.php
+++ b/tests/Feature/ImportDocumentBatchTest.php
@@ -5,12 +5,14 @@ namespace Tests\Feature;
use App\Console\Commands\ImportDocumentBatch;
use App\Jobs\ScanDocumentForMalware;
use App\Models\User;
+use App\Services\Malware\MalwareScanner;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
+use Tests\Support\SyntheticDocument;
use Tests\TestCase;
class ImportDocumentBatchTest extends TestCase
@@ -50,6 +52,7 @@ class ImportDocumentBatchTest extends TestCase
];
file_put_contents($this->staging.'/manifest.json', json_encode(['documents' => [$record, $record]], JSON_THROW_ON_ERROR));
$actor = User::factory()->create();
+ config(['portal.managers' => [$actor->email]]);
$this->artisan(new ImportDocumentBatch, ['manifest' => $this->batchName.'/manifest.json'])->assertSuccessful();
$this->assertDatabaseCount('documents', 0);
@@ -87,4 +90,51 @@ class ImportDocumentBatchTest extends TestCase
$this->artisan(new ImportDocumentBatch, ['manifest' => $this->batchName.'/manifest.json'])->assertFailed();
$this->assertDatabaseCount('documents', 0);
}
+
+ public function test_qa_batch_real_scan_preserves_original_replay_identity_conflict_and_profile_guards(): void
+ {
+ config(['services.malware.scanner' => 'clamd', 'services.malware.host' => '127.0.0.1', 'services.malware.port' => 3310]);
+ $scanner = app(MalwareScanner::class);
+ if (! $scanner->health()['available']) {
+ $this->markTestSkipped('Real ClamD required for batch evidence.');
+ }
+ $bytes = SyntheticDocument::pdf('Synthetic QA batch - no official or legal value');
+ file_put_contents($this->staging.'/source.pdf', $bytes);
+ $record = ['external_id' => 'qa-batch-v1', 'relative_path' => $this->batchName.'/source.pdf', 'title' => 'Synthetic QA batch',
+ 'issuer' => 'Synthetic QA issuer', 'source_url' => 'https://example.invalid/qa', 'version_label' => 'QA-1'];
+ file_put_contents($this->staging.'/manifest.json', json_encode(['documents' => [$record, $record]], JSON_THROW_ON_ERROR));
+ $actor = User::factory()->create();
+ $options = ['manifest' => $this->batchName.'/manifest.json', '--apply' => true, '--actor' => (string) $actor->id];
+ $this->artisan(new ImportDocumentBatch, $options)->assertFailed();
+ $this->assertDatabaseCount('documents', 0);
+ $this->assertSame([], Storage::disk('local')->allFiles('portal-documents'));
+ config(['portal.managers' => [$actor->email]]);
+ $this->app->detectEnvironment(fn () => 'production');
+ $this->artisan(new ImportDocumentBatch, $options)->assertFailed();
+ $this->app->detectEnvironment(fn () => 'testing');
+ $this->assertDatabaseCount('documents', 0);
+ $this->artisan(new ImportDocumentBatch, $options)->assertSuccessful();
+ $document = DB::table('documents')->firstOrFail();
+ $this->assertSame($bytes, Storage::disk('local')->get($document->storage_key));
+ $this->assertDatabaseCount('documents', 1);
+ $this->assertDatabaseCount('portal_resources', 1);
+ (new ScanDocumentForMalware($document->id))->handle($scanner);
+ $scanned = DB::table('documents')->where('id', $document->id)->first();
+ $this->assertSame('clean', $scanned->malware_scan_status);
+ $this->assertSame('ClamAV', $scanned->malware_engine);
+ $this->assertSame(hash('sha256', $bytes), $scanned->malware_scanned_sha256);
+ $response = $this->actingAs($actor)->get('/management/documents/'.$document->id.'/download')->assertOk();
+ $this->assertSame($bytes, file_get_contents($response->baseResponse->getFile()->getPathname()));
+ $resource = DB::table('portal_resources')->first();
+ $this->get('/documentos/'.$resource->id.'/download')->assertNotFound();
+ $this->artisan(new ImportDocumentBatch, $options)->assertSuccessful();
+ file_put_contents($this->staging.'/source.pdf', SyntheticDocument::pdf('Different QA bytes - same identity'));
+ $this->artisan(new ImportDocumentBatch, $options)->assertSuccessful();
+ $this->assertDatabaseCount('documents', 1);
+ $this->assertDatabaseCount('portal_resources', 1);
+ $this->assertSame($bytes, Storage::disk('local')->get($document->storage_key));
+ $this->assertDatabaseHas('portal_resources', ['id' => $resource->id, 'published' => false]);
+ $this->assertSame(1, DB::table('audit_events')->where('action', 'private_document_batch_imported')->count());
+ $this->actingAs(User::factory()->create())->get('/management/documents/'.$document->id.'/download')->assertForbidden();
+ }
}
diff --git a/tests/Feature/IndependentDocumentOperationsTest.php b/tests/Feature/IndependentDocumentOperationsTest.php
new file mode 100644
index 00000000..46376767
--- /dev/null
+++ b/tests/Feature/IndependentDocumentOperationsTest.php
@@ -0,0 +1,149 @@
+ 'clamd', 'services.malware.host' => '127.0.0.1', 'services.malware.port' => 3310]);
+ if (! app(MalwareScanner::class)->health()['available']) {
+ $this->markTestSkipped('Real ClamD required; no fabricated scan proof.');
+ }
+ }
+
+ private function files(): array
+ {
+ $image = imagecreatetruecolor(16, 16);
+ ob_start();
+ imagepng($image);
+ $png = ob_get_clean();
+ ob_start();
+ imagejpeg($image);
+ $jpeg = ob_get_clean();
+ imagedestroy($image);
+
+ return ['qa.pdf' => SyntheticDocument::pdf(), 'qa.png' => $png, 'qa.jpg' => $jpeg];
+ }
+
+ private function scan(string $id): object
+ {
+ (new ScanDocumentForMalware($id))->handle(app(MalwareScanner::class));
+ $document = DB::table('documents')->where('id', $id)->first();
+ $this->assertSame('active', $document->status);
+ $this->assertSame('clean', $document->malware_scan_status);
+ $this->assertSame('ClamAV', $document->malware_engine);
+ $this->assertSame(trim($document->sha256), $document->malware_scanned_sha256);
+ $this->assertNotNull($document->malware_signatures_at);
+
+ return $document;
+ }
+
+ public function test_land_pdf_png_jpeg_scan_recovery_print_and_profile_permissions_preserve_originals(): void
+ {
+ $owner = User::factory()->create();
+ $manager = User::factory()->create();
+ config(['portal.managers' => [$manager->email]]);
+ $this->actingAs($owner)->postJson('/investidor/terra-duat', ['payload' => ['full_name' => 'Synthetic QA investor']])->assertCreated();
+ $case = LandAssistanceCase::firstOrFail();
+ $base = '/investidor/terra-duat/'.$case->id;
+ foreach ($this->files() as $name => $bytes) {
+ $this->post($base.'/documentos', ['version' => $case->fresh()->version, 'category' => str_ends_with($name, '.pdf') ? 'prior_right' : 'photo',
+ 'file' => UploadedFile::fake()->createWithContent($name, $bytes)], ['Accept' => 'application/json'])->assertCreated();
+ $documentId = DB::table('documents')->where('file_name', $name)->value('id');
+ $link = DB::table('land_assistance_documents')->where('case_id', $case->id)->where('document_id', $documentId)->first();
+ $url = $base.'/documentos/'.$link->id;
+ $this->get($url)->assertNotFound();
+ $document = $this->scan($link->document_id);
+ $response = $this->get($url)->assertOk()->assertDownload($name);
+ $this->assertSame($bytes, file_get_contents($response->baseResponse->getFile()->getPathname()));
+ // Existing canonical encrypted originals must remain readable without making plaintext copies.
+ Storage::disk('local')->put($document->storage_key, Crypt::encryptString($bytes));
+ DB::table('documents')->where('id', $document->id)->update(['storage_encryption' => 'laravel']);
+ $this->get($url)->assertOk()->assertContent($bytes);
+ $this->assertSame($owner->id, $document->uploaded_by);
+ $this->assertSame(strlen($bytes), $document->size_bytes);
+ $this->actingAs($manager)->get($url)->assertNotFound();
+ $this->actingAs(User::factory()->create())->get($url)->assertNotFound();
+ $this->actingAs($owner)->getJson($base)->assertOk();
+ $this->assertSame($bytes, Crypt::decryptString(Storage::disk('local')->get($document->storage_key)));
+ Storage::disk('local')->put($document->storage_key, Crypt::encryptString('Tampered QA only'));
+ $this->get($url)->assertNotFound();
+ }
+ $this->get($base.'/imprimir')->assertOk(); // Printable response; browser PDF rendering remains pending.
+ $this->assertSame(3, DB::table('documents')->count());
+ $this->assertSame(3, DB::table('document_malware_scans')->where('result', 'clean')->count());
+ }
+
+ public function test_partnership_real_scans_sharing_revocation_new_session_and_encrypted_originals(): void
+ {
+ $owner = User::factory()->create();
+ $candidate = User::factory()->create();
+ $manager = User::factory()->create();
+ $outsider = User::factory()->create();
+ config(['portal.managers' => [$manager->email]]);
+ $exchange = app(PartnershipExchange::class);
+ $record = $exchange->save($owner, ['client_key' => (string) Str::uuid(), 'title' => 'Synthetic document QA partnership', 'kind' => 'seeking', 'partnership_type' => 'joint_venture',
+ 'offer' => 'Synthetic QA capacity', 'seeking' => 'Synthetic QA contribution', 'payload' => ['summary' => 'Synthetic QA only', 'consent' => true], 'origins' => [], 'locations' => []]);
+ $record = $exchange->transition($owner, $record->id, $record->version, 'submit', 'QA private document test');
+ $record = $exchange->transition($manager, $record->id, $record->version, 'publish', 'QA fixture only; no active disclosure');
+ $interest = $exchange->interest($candidate, $record->id, ['proposal' => 'Synthetic QA proposal', 'payload' => ['consent' => true]]);
+ $interest = $exchange->decideInterest($owner, $interest->id, $interest->version, 'shortlist', 'QA room preparation');
+ $exchange->decideInterest($owner, $interest->id, $interest->version, 'connect', 'QA private room access');
+ $room = DB::table('partnership_rooms')->where('interest_id', $interest->id)->first();
+ $base = '/parcerias/salas/'.$room->id;
+ foreach ($this->files() as $name => $bytes) {
+ $this->actingAs($owner)->post($base.'/documentos', ['shared' => false, 'file' => UploadedFile::fake()->createWithContent($name, $bytes)], ['Accept' => 'application/json'])->assertOk();
+ $link = DB::table('partnership_documents')->where('room_id', $room->id)->orderByDesc('id')->first();
+ $url = $base.'/documentos/'.$link->id;
+ $this->get($url)->assertNotFound();
+ $document = $this->scan($link->document_id);
+ $response = $this->get($url)->assertOk()->assertDownload($name);
+ $this->assertSame($bytes, file_get_contents($response->baseResponse->getFile()->getPathname()));
+ $this->actingAs($candidate)->get($url)->assertNotFound();
+ $this->postJson($url.'/partilha', ['shared' => true])->assertForbidden();
+ $this->actingAs($owner)->postJson($url.'/partilha', ['shared' => true])->assertOk();
+ Storage::disk('local')->put($document->storage_key, Crypt::encryptString($bytes));
+ DB::table('documents')->where('id', $document->id)->update(['storage_encryption' => 'laravel']);
+ $this->actingAs($candidate)->get($url)->assertOk()->assertContent($bytes);
+ $this->assertSame($owner->id, $document->uploaded_by);
+ $this->assertSame(strlen($bytes), $document->size_bytes);
+ // A new authentication context recovers shared documents from the repository.
+ auth()->logout();
+ $this->actingAs($candidate->fresh())->getJson($base)->assertOk()->assertJsonCount(1, 'documents');
+ $this->get($url)->assertOk()->assertContent($bytes);
+ $this->actingAs($manager)->get($url)->assertForbidden();
+ $this->actingAs($outsider)->get($url)->assertForbidden();
+ $this->actingAs($owner)->postJson($url.'/partilha', ['shared' => false])->assertOk();
+ $this->actingAs($candidate)->get($url)->assertNotFound();
+ $this->getJson($base)->assertOk()->assertJsonCount(0, 'documents');
+ $this->actingAs($owner)->get($url)->assertOk()->assertContent($bytes);
+ $this->assertSame($bytes, Crypt::decryptString(Storage::disk('local')->get($document->storage_key)));
+ Storage::disk('local')->put($document->storage_key, Crypt::encryptString('Tampered QA only'));
+ $this->get($url)->assertNotFound();
+ }
+ $this->assertSame(3, DB::table('documents')->count());
+ $this->assertSame(6, DB::table('partnership_events')->where('event_type', 'partnership.document_sharing_changed.v1')->count());
+ $this->assertSame(3, DB::table('document_malware_scans')->where('result', 'clean')->count());
+ }
+}
diff --git a/tests/Feature/OpportunityCanonicalWorkflowTest.php b/tests/Feature/OpportunityCanonicalWorkflowTest.php
new file mode 100644
index 00000000..a1fcaff5
--- /dev/null
+++ b/tests/Feature/OpportunityCanonicalWorkflowTest.php
@@ -0,0 +1,257 @@
+ true, 'portal.opportunity_specialized_drafts_enabled' => true]);
+ }
+
+ /** @param list $responsibilities */
+ private function actor(string $role, string $org, array $responsibilities = []): User
+ {
+ $user = User::factory()->create();
+ $user->forceFill(['two_factor_secret' => Crypt::encryptString('JBSWY3DPEHPK3PXP'), 'two_factor_confirmed_at' => now()])->save();
+ app(PortalProfileAdministration::class)->insertGrant((string) Str::uuid(), User::factory()->create(), [
+ 'user_id' => $user->id, 'role' => $role, 'organization_id' => $role === 'promoter' ? $org : null,
+ 'opportunity_types' => OpportunityManagement::CATEGORIES, 'responsibilities' => $responsibilities, 'source' => 'synthetic-policy-test-fixture']);
+
+ return $user;
+ }
+
+ private function loginFixture(User $user): static
+ {
+ // Policy fixture only. Real Fortify/ClamD evidence comes from the QA HTTP scenario.
+ return $this->actingAs($user)->withSession(['portal.mfa_actor' => $user->id, 'portal.mfa_at' => time(), 'portal.access_revision' => (int) $user->portal_access_revision]);
+ }
+
+ /** @param array $extra
+ * @return array */
+ private function action(User $user, int $id, string $action, array $extra = [], int $status = 200): array
+ {
+ $etag = app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id));
+ if ($action === 'publish') {
+ $extra = ['confirm_publication' => true, 'preview_hash' => Opportunity::findOrFail($id)->workflow_context['approval']['hash'] ?? str_repeat('0', 64), ...$extra];
+ }
+
+ return $this->loginFixture($user)->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $etag, 'action' => $action, 'reason' => self::REASON, ...$extra])->assertStatus($status)->json();
+ }
+
+ public function test_incomplete_drafts_preserve_category_rules_and_block_client_certification(): void
+ {
+ $service = app(OpportunityCanonicalContract::class);
+ foreach (OpportunityManagement::CATEGORIES as $category) {
+ $this->assertSame(['opportunity_category' => $category], $service->draft(['opportunity_category' => $category]));
+ }
+ $this->assertSame(['real_estate' => ['transaction_type' => 'sale', 'valuation' => []]], $service->draft(['real_estate' => ['transaction_type' => 'sale', 'valuation' => []]]));
+ $this->assertSame(['real_estate' => ['transaction_type' => null, 'land_area' => null, 'property_type' => null]], $service->draft(['real_estate' => ['transaction_type' => null, 'land_area' => null, 'property_type' => null]]));
+ foreach ([['land_rights' => ['operation_type' => 'land_sale']], ['business_transaction' => ['percentage_offered' => 101]], ['real_estate' => ['land_area' => -1]], ['approved_by' => 99], ['evidences' => [['verified' => true]]]] as $invalid) {
+ try {
+ $service->draft($invalid);
+ $this->fail('Invalid provided data or response metadata must be rejected.');
+ } catch (ValidationException $e) {
+ $this->assertNotEmpty($e->errors());
+ }
+ }
+ $schema = $service->schema();
+ $this->assertNotEmpty($schema['$defs']['opportunityCreate']['allOf']);
+ $this->assertNotEmpty($schema['$defs']['realEstateCreate']['allOf']);
+ $this->assertNotEmpty($schema['$defs']['landRightsCreate']['allOf']);
+ $this->assertNotEmpty($schema['$defs']['businessTransactionCreate']['allOf']);
+ }
+
+ public function test_correction_approval_publication_material_revision_and_suspension_preserve_authorization(): void
+ {
+ [$id, $promoter, $validator, $publisher, $payload, $document] = $this->fixture();
+ $this->action($promoter, $id, 'submit');
+ $this->action($validator, $id, 'approve', [], 422);
+ $this->action($validator, $id, 'start_review');
+ $firstReview = Opportunity::findOrFail($id)->workflow_context['review_task_id'];
+ $this->action($validator, $id, 'request_correction', ['correction_items' => ['canonical.executive_summary']]);
+ $this->assertDatabaseHas('tasks', ['id' => $firstReview, 'status' => 'done']);
+ $payload['executive_summary'] .= ' Corrigido em QA.';
+ // Primary is deliberately second: array order must not change the public territory.
+ $primary = DB::table('opportunity_location_drafts')->where('id', $payload['locations'][0])->first();
+ $primaryData = json_decode($primary->payload, true);
+ $secondaryId = (string) Str::uuid();
+ $secondaryDistrict = (string) Str::uuid();
+ DB::table('geo_locations')->insert(['id' => $secondaryDistrict, 'code' => $secondaryDistrict, 'name' => 'Non-primary QA district', 'location_type' => 'district', 'parent_id' => $primaryData['province_id'], 'data_classification' => 'internal']);
+ DB::table('opportunity_location_drafts')->insert(['id' => $secondaryId, 'opportunity_id' => $id, 'version' => 1, 'created_by' => $promoter->id, 'payload' => json_encode([...$primaryData, 'district_id' => $secondaryDistrict, 'is_primary' => false])]);
+ $payload['locations'] = [$secondaryId, $payload['locations'][0]];
+ $payload['location_mode'] = 'multiple';
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'canonical' => $payload, 'reason' => self::REASON])->assertOk();
+ $this->action($promoter, $id, 'submit');
+ $this->assertArrayNotHasKey('assignment', Opportunity::findOrFail($id)->workflow_context);
+ $this->action($validator, $id, 'start_review');
+ foreach (['property_review', 'registry_urban_review', 'building_compliance_review'] as $gate) {
+ $this->action($validator, $id, 'review_gate', ['gate' => $gate, 'gate_decision' => 'approved', 'evidence_document_ids' => [$document]]);
+ }
+ app(PortalProfileAdministration::class)->insertGrant((string) Str::uuid(), User::factory()->create(), ['user_id' => $promoter->id, 'role' => 'validator', 'opportunity_types' => ['real_estate'], 'responsibilities' => ['technical_reviewer', 'legal_reviewer']]);
+ $this->action($promoter, $id, 'approve', [], 403);
+ $this->action($validator, $id, 'approve');
+ app(PortalProfileAdministration::class)->insertGrant((string) Str::uuid(), User::factory()->create(), ['user_id' => $validator->id, 'role' => 'publisher', 'opportunity_types' => ['real_estate']]);
+ $this->action($validator, $id, 'publish', [], 403);
+ $this->action($publisher, $id, 'assign_publication', ['assignee_user_id' => $publisher->id]);
+ $otherPublisher = $this->actor('publisher', 'unused');
+ $this->action($otherPublisher, $id, 'publish', [], 403);
+ $grants = DB::table('portal_role_assignments')->where('user_id', $validator->id)->where('role', 'validator')->whereNull('revoked_at')->pluck('id');
+ DB::table('portal_role_assignments')->whereIn('id', $grants)->update(['revoked_at' => now()]);
+ $this->action($publisher, $id, 'publish', [], 403);
+ DB::table('portal_role_assignments')->whereIn('id', $grants)->update(['revoked_at' => null]);
+ $this->action($publisher, $id, 'publish');
+ $this->assertSame($primaryData['district_id'], Opportunity::findOrFail($id)->primary_territory_id);
+ $publicTitle = Opportunity::findOrFail($id)->title;
+ $this->assertSame(0, Opportunity::published()->count(), 'Internal publication must not leak to public consumers.');
+ $this->action($promoter, $id, 'request_revision');
+ $payload['official_title'] = 'Título materialmente alterado, ainda privado';
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'canonical' => $payload, 'reason' => self::REASON])->assertOk();
+ $record = Opportunity::findOrFail($id);
+ $this->assertSame('published', $record->status);
+ $this->assertSame($publicTitle, $record->title);
+ $this->assertArrayNotHasKey('approval', $record->workflow_context);
+ $this->assertSame('needs_information', $record->workflow_context['working_state']);
+ $this->get('/minhas-oportunidades?status=needs_information&q=materialmente')->assertInertia(fn (Assert $p) => $p->where('records.total', 1)->where('records.data.0.draft_title', 'Título materialmente alterado, ainda privado')->where('counts.needs_information', 1));
+ $this->action($publisher, $id, 'publish', [], 409);
+ $this->action($publisher, $id, 'suspend');
+ $this->assertSame('suspended', Opportunity::findOrFail($id)->status);
+ $this->assertDatabaseHas('tasks', ['source_system' => 'opportunity-workflow', 'task_type' => 'opportunity_review', 'assignee_user_id' => $validator->id, 'due_at' => null, 'status' => 'done']);
+ $this->assertSame('clean', DB::table('documents')->where('id', DB::table('opportunity_documents')->where('id', $document)->value('document_id'))->value('malware_scan_status'));
+ }
+
+ public function test_invalid_binding_reason_and_original_integrity_cannot_be_bypassed(): void
+ {
+ [$id, $promoter, $validator, $publisher, $payload, $document] = $this->fixture();
+ $bad = $payload;
+ $bad['real_estate']['price'] = null;
+ $bad['documents'] = [(string) Str::uuid()];
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'canonical' => $bad, 'reason' => self::REASON])->assertOk();
+ $this->action($promoter, $id, 'submit', [], 422);
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'canonical' => $payload, 'reason' => self::REASON])->assertOk();
+ $this->action($promoter, $id, 'submit');
+ $this->action($validator, $id, 'reject', ['reason' => 'curto'], 422);
+ $this->action($validator, $id, 'reject');
+ $this->assertDatabaseHas('tasks', ['id' => Opportunity::findOrFail($id)->workflow_context['review_task_id'], 'status' => 'done']);
+ $this->assertSame(self::REASON, Opportunity::findOrFail($id)->workflow_context['rejection']['reason']);
+ $this->action($promoter, $id, 'appeal');
+ $this->action($validator, $id, 'appeal_reopen', [], 403);
+ $appeal = $this->actor('validator', $promoter->id.'unused', ['appeal_reviewer']);
+ $this->action($appeal, $id, 'appeal_reopen');
+ $this->assertFalse(Opportunity::findOrFail($id)->workflow_context['appeal']['pending']);
+ $storageKey = DB::table('documents')->where('id', DB::table('opportunity_documents')->where('id', $document)->value('document_id'))->value('storage_key');
+ Storage::disk('local')->put($storageKey, 'Invalid ciphertext - synthetic QA only');
+ $this->action($promoter, $id, 'submit', [], 404);
+ $this->loginFixture($promoter)->get('/minhas-oportunidades/'.$id.'/resources/documents/'.$document.'/download')->assertNotFound();
+ }
+
+ public function test_semantic_errors_are_keyed_to_fields_and_incomplete_drafts_remain_recoverable(): void
+ {
+ [$id,$promoter,$validator,$publisher,$payload,$document] = $this->fixture();
+ foreach (['utilities', 'title_document_id', 'occupancy_document_id', 'valuation.value'] as $field) {
+ $bad = $payload;
+ if ($field === 'utilities') {
+ $bad['real_estate']['utilities'] = [];
+ } elseif ($field === 'title_document_id') {
+ unset($bad['real_estate'][$field]);
+ } elseif ($field === 'valuation.value') {
+ $bad['real_estate']['valuation']['value'] = 0;
+ } else {
+ $bad['real_estate']['occupancy_status'] = 'tenant_occupied';
+ }
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'canonical' => $bad, 'reason' => self::REASON])->assertOk();
+ $this->get('/minhas-oportunidades/'.$id.'/edit')->assertInertia(fn (Assert $page) => $page->where('values.canonical', $bad));
+ $this->loginFixture($promoter)->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id)), 'action' => 'submit', 'reason' => self::REASON])->assertUnprocessable()->assertJsonValidationErrors('canonical.real_estate.'.$field);
+ }
+ }
+
+ public function test_scoped_opinion_tasks_require_the_recipient_and_do_not_approve_a_gate(): void
+ {
+ [$id,$promoter,$validator,$publisher,$payload,$document] = $this->fixture();
+ $opinionReviewer = $this->actor('validator', 'unused', ['technical_reviewer']);
+ $this->action($promoter, $id, 'submit');
+ $this->action($validator, $id, 'start_review');
+ $this->action($validator, $id, 'pending_opinion', ['gate' => 'property_review', 'recipient_user_id' => $opinionReviewer->id]);
+ $context = Opportunity::findOrFail($id)->workflow_context;
+ $opinion = array_key_first($context['opinions']);
+ $this->action($validator, $id, 'approve', [], 422);
+ $this->action($validator, $id, 'respond_opinion', ['opinion_id' => $opinion, 'gate_decision' => 'approved', 'evidence_document_ids' => [$document]], 403);
+ $this->loginFixture($opinionReviewer)->get('/minhas-oportunidades?queue=assigned')->assertInertia(fn (Assert $p) => $p->where('records.total', 1));
+ $this->action($opinionReviewer, $id, 'respond_opinion', ['opinion_id' => $opinion, 'gate_decision' => 'approved', 'evidence_document_ids' => [$document]]);
+ $context = Opportunity::findOrFail($id)->workflow_context;
+ $this->assertSame('answered', $context['opinions'][$opinion]['status']);
+ $this->assertArrayNotHasKey('reviews', $context);
+ $this->assertDatabaseHas('tasks', ['id' => $context['opinions'][$opinion]['task_id'], 'status' => 'done']);
+ $this->action($validator, $id, 'approve', [], 422);
+ }
+
+ /** @return array{int,User,User,User,array,string} */
+ private function fixture(): array
+ {
+ $org = (string) Str::uuid();
+ DB::table('organizations')->insert(['id' => $org, 'name' => 'Synthetic QA organization', 'organization_type' => 'private']);
+ $promoter = $this->actor('promoter', $org);
+ DB::table('memberships')->insert(['id' => (string) Str::uuid(), 'user_id' => $promoter->id, 'organization_id' => $org, 'role' => 'officer']);
+ $validator = $this->actor('validator', $org, ['technical_reviewer', 'legal_reviewer', 'validation_coordinator']);
+ $publisher = $this->actor('publisher', $org, ['publication_coordinator']);
+ $version = (string) Str::uuid();
+ DB::table('reference_catalog_versions')->insert(['id' => $version, 'catalog_code' => 'qa-only', 'version_no' => 1, 'source_system' => 'synthetic-policy-fixture', 'source_version' => 'qa', 'source_reference' => 'Not official', 'status' => 'published']);
+ $ids = [];
+ $parent = null;
+ foreach (range(1, 3) as $i) {
+ $sector = DB::table('sectors')->insertGetId(['name' => 'QA '.$i, 'slug' => 'qa-'.$i, 'is_active' => true]);
+ $id = (string) Str::uuid();
+ DB::table('economic_activities')->insert(['id' => $id, 'parent_id' => $parent, 'sector_id' => $sector, 'catalog_version_id' => $version, 'code' => 'qa-'.$i, 'label_pt_mz' => 'QA '.$i, 'status' => 'published', 'valid_from' => today()]);
+ $ids[] = [$id, $sector];
+ $parent = $id;
+ }
+ $contact = (string) Str::uuid();
+ $investor = (string) Str::uuid();
+ DB::table('contacts')->insert(['id' => $contact, 'full_name' => 'Synthetic QA contact']);
+ DB::table('investors')->insert(['id' => $investor, 'organization_id' => $org, 'legal_name' => 'Synthetic QA entity', 'investor_type' => 'institutional', 'status' => 'active']);
+ DB::table('investor_contacts')->insert(['investor_id' => $investor, 'contact_id' => $contact]);
+ $draft = $this->loginFixture($promoter)->postJson('/minhas-oportunidades/drafts', ['creation_key' => (string) Str::uuid(), 'organization_id' => $org, 'opportunity_category' => 'real_estate', 'reason' => self::REASON])->assertCreated()->json();
+ $id = $draft['id'];
+ $location = (string) Str::uuid();
+ $provinceId = (string) Str::uuid();
+ $districtId = (string) Str::uuid();
+ DB::table('geo_locations')->insert([['id' => $provinceId, 'code' => $provinceId, 'name' => 'Synthetic QA province', 'location_type' => 'province', 'parent_id' => null, 'data_classification' => 'internal'], ['id' => $districtId, 'code' => $districtId, 'name' => 'Synthetic QA district', 'location_type' => 'district', 'parent_id' => $provinceId, 'data_classification' => 'internal']]);
+ $province = DB::table('geo_locations')->where('id', $provinceId)->first();
+ $district = DB::table('geo_locations')->where('id', $districtId)->first();
+ DB::table('opportunity_location_drafts')->insert(['id' => $location, 'opportunity_id' => $id, 'version' => 1, 'created_by' => $promoter->id, 'payload' => json_encode(['country_code' => 'MZ', 'province_id' => $province->id, 'district_id' => $district->id, 'role' => 'headquarters', 'is_primary' => true])]);
+ $document = (string) Str::uuid();
+ $file = (string) Str::uuid();
+ $bytes = 'Synthetic policy fixture, not a real scanner result.';
+ $key = 'opportunity-contract-test/'.$file;
+ Storage::disk('local')->put($key, Crypt::encryptString($bytes));
+ DB::table('documents')->insert(['id' => $file, 'file_name' => 'qa-fixture.txt', 'storage_key' => $key, 'storage_encryption' => 'laravel', 'media_type' => 'text/plain', 'sha256' => hash('sha256', $bytes), 'status' => 'active', 'malware_scan_status' => 'clean', 'malware_engine' => 'synthetic-policy-fixture', 'malware_scanned_sha256' => hash('sha256', $bytes), 'uploaded_by' => $promoter->id]);
+ DB::table('opportunity_documents')->insert(['id' => $document, 'opportunity_id' => $id, 'document_id' => $file, 'version' => 1, 'created_by' => $promoter->id, 'payload' => json_encode(['title' => 'QA', 'category' => 'qa', 'visibility' => 'internal'])]);
+ $payload = ['opportunity_category' => 'real_estate', 'official_title' => 'Imóvel sintético para ensaio QA', 'promoter_id' => $org, 'promoter_type' => 'private', 'internal_contact_id' => $contact, 'sector_id' => $ids[0][1], 'subsector_id' => $ids[1][0], 'economic_activity_id' => $ids[2][0], 'location_mode' => 'single', 'geographic_scope' => 'district', 'locations' => [$location], 'executive_summary' => trim(str_repeat('Resumo sintético QA. ', 20)), 'demand_statement' => trim(str_repeat('Necessidade sintética QA. ', 6)), 'documents' => [$document], 'evidences' => [['title' => 'QA', 'evidence_type' => 'qa', 'document_id' => $document]], 'publication_languages' => [['language_code' => 'pt-MZ', 'title' => 'QA', 'summary' => 'QA']], 'visibility' => 'internal', 'currency' => 'MZN', 'truth_declaration' => true, 'real_estate' => ['transaction_type' => 'sale', 'property_type' => 'warehouse', 'construction_status' => 'completed', 'property_condition' => 'good', 'land_area' => 1000, 'built_area' => 500, 'area_unit' => 'sqm', 'utilities' => [['type' => 'water', 'status' => 'existing']], 'occupancy_status' => 'vacant', 'title_type' => 'QA', 'registration_number' => 'QA-'.$id, 'encumbrances' => [['type' => 'none']], 'valuation' => ['value' => 1000, 'date' => '2026-10-10', 'method' => 'qa', 'appraiser' => 'QA', 'document_id' => $document], 'price' => 1000, 'use_license_document_id' => $document]];
+ $authority = (string) Str::uuid();
+ DB::table('authorities')->insert(['id' => $authority, 'catalog_version_id' => $version, 'organization_id' => $org, 'code' => 'QA-'.$id, 'authority_type' => 'qa-synthetic', 'label_pt_mz' => 'Entidade sintética QA', 'source_reference' => 'Synthetic policy fixture; not official', 'valid_from' => '2026-01-01', 'status' => 'published']);
+ $payload['real_estate']['utilities'] = array_map(fn ($type) => ['type' => $type, 'status' => 'existing'], ['electricity', 'water', 'sanitation', 'telecommunications', 'access']);
+ $payload['real_estate'] += ['title_document_id' => $document, 'title_holder_name' => 'Synthetic QA organization', 'issuing_authority_id' => $authority];
+ $this->loginFixture($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $draft['etag'], 'canonical' => $payload, 'reason' => self::REASON])->assertOk();
+
+ return [$id, $promoter, $validator, $publisher, $payload, $document];
+ }
+}
diff --git a/tests/Feature/OpportunityPublicationScopeTest.php b/tests/Feature/OpportunityPublicationScopeTest.php
new file mode 100644
index 00000000..86811e4b
--- /dev/null
+++ b/tests/Feature/OpportunityPublicationScopeTest.php
@@ -0,0 +1,34 @@
+create();
+ $id = DB::table('opportunities')->insertGetId(['reference' => 'QA-publication-scope', 'slug' => 'qa-publication-scope', 'status' => 'approved',
+ 'owner_user_id' => $owner->id, 'workflow_context' => json_encode(['publication' => ['visibility' => 'public']])]);
+ $record = Opportunity::findOrFail($id);
+ $this->assertSame('unpublished', $record->publicationPresentation()['scope']);
+ $record->forceFill(['status' => 'published', 'published_at' => now(), 'workflow_context' => ['publication' => ['visibility' => 'internal']]])->save();
+ $this->assertSame('restricted', $record->publicationPresentation()['scope']);
+ $this->assertFalse($record->publicationPresentation()['public_catalog']);
+ $this->assertFalse(Opportunity::published()->whereKey($id)->exists());
+ $record->forceFill(['workflow_context' => ['publication' => ['visibility' => 'public']]])->save();
+ $this->assertTrue($record->publicationPresentation()['public_catalog']);
+ $this->assertSame('public', $record->publicationPresentation()['scope']);
+ $record->forceFill(['status' => 'suspended'])->save();
+ $this->assertSame('unpublished', $record->publicationPresentation()['scope']);
+ $record->forceFill(['status' => 'published', 'published_at' => now()->addDay()])->save();
+ $this->assertFalse($record->publicationPresentation()['public_catalog']);
+ }
+}
diff --git a/tests/Feature/OpportunityRealEstateDraftTest.php b/tests/Feature/OpportunityRealEstateDraftTest.php
new file mode 100644
index 00000000..3dc61b48
--- /dev/null
+++ b/tests/Feature/OpportunityRealEstateDraftTest.php
@@ -0,0 +1,56 @@
+create();
+ config(['portal.managers' => [$manager->email], 'portal.opportunity_specialized_drafts_enabled' => true]);
+ $payload = ['creation_key' => (string) Str::uuid(), 'opportunity_category' => 'real_estate', 'title' => 'QA imóvel incompleto', 'real_estate' => ['transaction_type' => 'lease', 'land_area' => 250.5, 'area_unit' => 'sqm'], 'reason' => 'Rascunho imobiliário incompleto sem decisão externa'];
+ $draft = $this->actingAs($manager)->postJson('/management/opportunities/drafts', $payload)->assertCreated()->json();
+ $this->postJson('/management/opportunities/drafts', $payload)->assertCreated()->assertJsonPath('id', $draft['id']);
+ $this->assertSame(1, Opportunity::count());
+ $path = '/management/opportunities/'.$draft['id'].'/edit';
+ $this->get($path)->assertInertia(fn (Assert $page) => $page->where('values.real_estate.land_area', 250.5)->where('record.status', 'draft'));
+ $this->putJson('/management/opportunities/'.$draft['id'].'/draft', ['etag' => $draft['etag'], 'real_estate' => ['rent' => 1000, 'rent_periodicity' => 'monthly'], 'reason' => 'Complemento de renda no mesmo rascunho imobiliário'])->assertOk();
+ $this->get($path)->assertInertia(fn (Assert $page) => $page->where('values.real_estate.land_area', 250.5)->where('values.real_estate.rent', 1000));
+ $record = Opportunity::findOrFail($draft['id']);
+ $before = $record->getRawOriginal();
+ foreach ([['price' => 0], ['price' => '100'], ['transaction_type' => 'sell_duat'], ['id' => (string) Str::uuid()], ['utilities' => ['invalid scalar']], ['planning_permit_document_id' => 'not-uuid']] as $invalid) {
+ $this->putJson('/management/opportunities/'.$draft['id'].'/draft', ['etag' => app(OpportunityManagement::class)->etag($record), 'real_estate' => $invalid, 'reason' => 'Negativo contratual que deve conservar o rascunho'])->assertUnprocessable();
+ $this->assertSame($before, $record->fresh()->getRawOriginal());
+ }
+ $this->actingAs(User::factory()->create())->get($path)->assertForbidden();
+ $this->assertSame(0, Opportunity::published()->count());
+ }
+
+ public function test_specialized_draft_never_changes_published_version_and_is_disabled_by_default(): void
+ {
+ $manager = User::factory()->create();
+ config(['portal.managers' => [$manager->email]]);
+ $this->actingAs($manager)->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid(), 'opportunity_category' => 'real_estate', 'real_estate' => ['transaction_type' => 'sale'], 'reason' => 'Incremento desativado mantém compatibilidade ativa'])->assertUnprocessable();
+ $this->assertSame(0, Opportunity::count());
+ config(['portal.opportunity_specialized_drafts_enabled' => true]);
+ $sector = Sector::create(['name' => 'QA imóveis', 'slug' => 'qa-real-estate', 'is_active' => true, 'sort_order' => 1]);
+ $record = Opportunity::create(['title' => 'QA published original', 'reference' => 'QA-RE-PUBLISHED', 'slug' => 'qa-re-published', 'sector_id' => $sector->id, 'status' => 'published', 'published_at' => now(), 'opportunity_category' => 'real_estate', 'management_version' => 1]);
+ $record->forceFill(['opportunity_category' => 'real_estate'])->save();
+ $this->putJson('/management/opportunities/'.$record->id.'/draft', ['etag' => app(OpportunityManagement::class)->etag($record), 'real_estate' => ['transaction_type' => 'sale', 'price' => 50000], 'reason' => 'Nova proposta privada sem alteração da ficha publicada'])->assertOk();
+ $this->assertSame('QA published original', $record->fresh()->title);
+ $this->assertSame('published', $record->fresh()->status);
+ $this->getJson('/api/v1/opportunities/qa-re-published')->assertOk()->assertJsonMissingPath('data.real_estate')->assertJsonMissingPath('data.management_draft');
+ $this->assertSame(50000, json_decode($record->fresh()->management_draft, true)['real_estate']['price']);
+ }
+}
diff --git a/tests/Feature/OpportunityResourcesTest.php b/tests/Feature/OpportunityResourcesTest.php
index 2e356dff..fdad11af 100644
--- a/tests/Feature/OpportunityResourcesTest.php
+++ b/tests/Feature/OpportunityResourcesTest.php
@@ -21,6 +21,7 @@ class OpportunityResourcesTest extends TestCase
{
use RefreshDatabase;
+ /** @return array{User,Opportunity} */
private function setupDraft(): array
{
Storage::fake('local');
@@ -28,10 +29,15 @@ class OpportunityResourcesTest extends TestCase
$user = User::factory()->create();
config(['portal.managers' => [$user->email]]);
$id = $this->actingAs($user)->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid(), 'reason' => 'Rascunho de recursos em QA isolada'])->assertCreated()->json('id');
+ if (! is_int($id)) {
+ throw new \RuntimeException('O cadastro QA deve devolver um ID inteiro de oportunidade.');
+ }
return [$user, Opportunity::findOrFail($id)];
}
+ /** @param array $payload
+ * @return array */
private function payload(Opportunity $opportunity, array $payload = []): array
{
return ['etag' => app(OpportunityManagement::class)->etag($opportunity), 'creation_key' => (string) Str::uuid(), 'payload' => $payload, 'reason' => 'Preparação e conferência em QA isolada'];
@@ -64,6 +70,7 @@ class OpportunityResourcesTest extends TestCase
$life = ['etag' => app(OpportunityManagement::class)->etag($o->fresh()), 'version' => 2, 'action' => 'delete', 'confirm' => true, 'reason' => 'Exclusão lógica de anexo apenas QA'];
$this->postJson('/management/opportunities/'.$o->id.'/resources/documents/'.$r->id.'/lifecycle', $life)->assertOk();
$this->assertSoftDeleted('opportunity_documents', ['id' => $r->id]);
+ $this->get('/management/opportunities/'.$o->id.'/resources/documents/'.$r->id.'/download')->assertNotFound();
$this->postJson('/management/opportunities/'.$o->id.'/resources/documents/'.$r->id.'/lifecycle', [...$life, 'etag' => app(OpportunityManagement::class)->etag($o->fresh()), 'version' => 3, 'action' => 'restore'])->assertOk();
$this->assertDatabaseHas('opportunity_documents', ['id' => $r->id, 'deleted_at' => null, 'version' => 4]);
$this->assertSame(4, DB::table('audit_events')->where('source_system', 'opportunity-resources')->count());
@@ -122,7 +129,11 @@ class OpportunityResourcesTest extends TestCase
$this->assertSame('pending', $document->malware_scan_status);
$webp = Crypt::decryptString(Storage::disk('local')->get($document->storage_key));
$this->assertStringNotContainsString('EXIF', $webp);
- $this->assertSame('image/webp', getimagesizefromstring($webp)['mime']);
+ $size = getimagesizefromstring($webp);
+ if ($size === false) {
+ throw new \RuntimeException('Derivada QA não contém uma imagem válida.');
+ }
+ $this->assertSame('image/webp', $size['mime']);
(new ScanDocumentForMalware($document->id))->handle(new CleanScannerFixture);
}
$preview = URL::temporarySignedRoute('management.opportunity-image-preview', now()->addMinutes(10), ['id' => $o->id, 'resourceId' => $image->id, 'documentId' => $payload['derivatives'][0]['document_id']]);
diff --git a/tests/Feature/PortalProfileAccessTest.php b/tests/Feature/PortalProfileAccessTest.php
new file mode 100644
index 00000000..6e59d9ea
--- /dev/null
+++ b/tests/Feature/PortalProfileAccessTest.php
@@ -0,0 +1,263 @@
+ true]);
+ }
+
+ private function actor(): User
+ {
+ $user = User::factory()->create();
+ $user->forceFill(['two_factor_secret' => Crypt::encryptString('JBSWY3DPEHPK3PXP'), 'two_factor_confirmed_at' => now()])->save();
+
+ return $user;
+ }
+
+ private function organization(User ...$users): string
+ {
+ $id = (string) Str::uuid();
+ DB::table('organizations')->insert(['id' => $id, 'name' => 'QA synthetic organization', 'organization_type' => 'private']);
+ foreach ($users as $user) {
+ DB::table('memberships')->insert(['id' => (string) Str::uuid(), 'user_id' => $user->id, 'organization_id' => $id, 'role' => 'officer']);
+ }
+
+ return $id;
+ }
+
+ private function grant(User $user, string $role, ?string $organization = null, array $types = ['investment_project']): string
+ {
+ $id = (string) Str::uuid();
+ app(PortalProfileAdministration::class)->insertGrant($id, $this->actor(), ['user_id' => $user->id, 'role' => $role, 'organization_id' => $organization,
+ 'opportunity_types' => $types, 'source' => 'synthetic-test-fixture']);
+
+ return $id;
+ }
+
+ private function mfa(User $user): static
+ {
+ return $this->actingAs($user)->withSession(['portal.mfa_actor' => $user->id, 'portal.mfa_at' => time(), 'portal.access_revision' => (int) $user->fresh()->portal_access_revision]);
+ }
+
+ private function draft(User $user, ?string $organization = null): array
+ {
+ return $this->actingAs($user)->postJson('/minhas-oportunidades/drafts', ['creation_key' => (string) Str::uuid(), 'organization_id' => $organization,
+ 'opportunity_category' => 'investment_project', 'title' => 'QA private opportunity', 'reason' => self::REASON])->assertCreated()->json();
+ }
+
+ public function test_public_profile_requests_are_owned_idempotent_and_not_self_activating(): void
+ {
+ $user = User::factory()->create();
+ $other = User::factory()->create();
+ $this->actingAs($user)->get('/dashboard')->assertInertia(fn (Assert $p) => $p->where('profileAccess.mine', null)->where('profileAccess.request', '/perfil/promotor'));
+ $this->postJson('/minhas-oportunidades/drafts', ['creation_key' => (string) Str::uuid(), 'opportunity_category' => 'investment_project'])->assertForbidden();
+ $doc = (string) Str::uuid();
+ // This is an authorization fixture, not evidence of a real antimalware scan.
+ DB::table('documents')->insert(['id' => $doc, 'file_name' => 'synthetic.txt', 'storage_key' => 'synthetic/'.$doc, 'media_type' => 'text/plain',
+ 'sha256' => str_repeat('a', 64), 'malware_scanned_sha256' => str_repeat('a', 64), 'status' => 'active', 'malware_scan_status' => 'clean', 'uploaded_by' => $user->id]);
+ $payload = ['creation_key' => (string) Str::uuid(), 'representation_type' => 'individual', 'opportunity_types' => ['investment_project'], 'document_ids' => [$doc], 'reason' => self::REASON];
+ $id = $this->postJson('/perfil/promotor', $payload)->assertCreated()->json('id');
+ $this->postJson('/perfil/promotor', $payload)->assertCreated()->assertJsonPath('id', $id);
+ $this->postJson('/perfil/promotor', [...$payload, 'reason' => self::REASON.' changed'])->assertConflict();
+ $this->getJson('/perfil/promotor/'.$id)->assertOk()->assertJsonPath('status', 'pending');
+ $this->assertFalse(app(PortalProfileAccess::class)->has($user, 'promoter'));
+ $this->getJson('/minhas-oportunidades/territory-options?type=province')->assertForbidden();
+ $this->actingAs($other)->getJson('/perfil/promotor/'.$id)->assertForbidden();
+ $this->postJson('/perfil/promotor', [...$payload, 'creation_key' => (string) Str::uuid()])->assertUnprocessable();
+ }
+
+ public function test_promoters_share_authorized_organization_drafts_but_not_other_scopes_or_types(): void
+ {
+ $author = $this->actor();
+ $colleague = $this->actor();
+ $outsider = $this->actor();
+ $organization = $this->organization($author, $colleague);
+ $otherOrganization = $this->organization($outsider);
+ $this->grant($author, 'promoter', $organization);
+ $this->grant($colleague, 'promoter', $organization);
+ $this->grant($outsider, 'promoter', $otherOrganization);
+ $draft = $this->draft($author, $organization);
+ $id = $draft['id'];
+ $this->get('/dashboard')->assertInertia(fn (Assert $p) => $p->where('profileAccess.mine', '/minhas-oportunidades')->where('profileAccess.create', '/minhas-oportunidades/create'));
+ $this->actingAs($colleague)->get('/minhas-oportunidades/'.$id.'/edit')->assertInertia(fn (Assert $p) => $p->where('values.title', 'QA private opportunity')->where('readOnly', false));
+ $update = $this->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $draft['etag'], 'title' => 'QA shared edit', 'reason' => self::REASON])->assertOk()->json();
+ $this->assertSame($author->id, (int) Opportunity::findOrFail($id)->owner_user_id);
+ $this->assertSame([$author->id, $colleague->id], Opportunity::findOrFail($id)->workflow_context['contributors']);
+ $this->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $update['etag'], 'organization_id' => $otherOrganization, 'reason' => self::REASON])->assertForbidden();
+ $this->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $update['etag'], 'opportunity_category' => 'financing', 'reason' => self::REASON])->assertForbidden();
+ $this->actingAs($outsider)->get('/minhas-oportunidades/'.$id.'/view')->assertForbidden();
+ $this->postJson('/minhas-oportunidades/drafts', ['creation_key' => (string) Str::uuid(), 'organization_id' => $organization, 'opportunity_category' => 'investment_project', 'reason' => self::REASON])->assertForbidden();
+ $this->get('/minhas-oportunidades')->assertInertia(fn (Assert $p) => $p->where('records.total', 0));
+ DB::table('memberships')->where('user_id', $colleague->id)->update(['deleted_at' => now()]);
+ $this->actingAs($colleague)->get('/minhas-oportunidades/'.$id.'/view')->assertForbidden();
+ }
+
+ public function test_profile_decisions_do_not_fabricate_checks_and_privileged_grants_require_confirmed_mfa(): void
+ {
+ $first = $this->actor();
+ $second = $this->actor();
+ $bootstrap = $this->actor();
+ config(['portal_profiles.bootstrap_authorized' => true]);
+ $this->mfa($bootstrap);
+ app(PortalSuperusers::class)->initialize($first, $second, $bootstrap);
+ $doc = (string) Str::uuid();
+ DB::table('documents')->insert(['id' => $doc, 'file_name' => 'synthetic-authorization-fixture.txt', 'storage_key' => 'synthetic/'.$doc,
+ 'media_type' => 'text/plain', 'sha256' => str_repeat('b', 64), 'malware_scanned_sha256' => str_repeat('b', 64),
+ 'status' => 'active', 'malware_scan_status' => 'clean', 'uploaded_by' => $first->id]);
+ $request = $this->mfa($first)->postJson('/perfil/promotor', ['creation_key' => (string) Str::uuid(), 'representation_type' => 'individual',
+ 'opportunity_types' => ['investment_project'], 'document_ids' => [$doc], 'reason' => self::REASON])->assertCreated()->json('id');
+ $decision = ['version' => 1, 'decision' => 'rejected', 'reason' => self::REASON, 'approved_types' => [],
+ 'verified_identity' => false, 'verified_representation' => false, 'verified_documents' => false];
+ $this->postJson('/perfis/pedidos/'.$request.'/decisao', $decision)->assertForbidden();
+ $this->mfa($second)->postJson('/perfis/pedidos/'.$request.'/decisao', $decision)->assertOk();
+ $this->assertDatabaseHas('portal_profile_requests', ['id' => $request, 'status' => 'rejected']);
+ $this->assertFalse(app(PortalProfileAccess::class)->has($first, 'promoter'));
+ $event = json_decode(DB::table('audit_events')->where('action', 'promoter_request_decided')->value('after_data'), true);
+ $this->assertFalse($event['checks']['verified_documents']);
+ $unenrolled = User::factory()->create();
+ $this->postJson('/perfis/atribuicoes', ['user_id' => $unenrolled->id, 'role' => 'validator',
+ 'opportunity_types' => ['investment_project'], 'reason' => self::REASON])->assertUnprocessable();
+ $this->postJson('/perfis/atribuicoes', ['user_id' => $bootstrap->id, 'role' => 'auditor', 'responsibilities' => ['validation_coordinator'],
+ 'opportunity_types' => ['investment_project'], 'reason' => self::REASON])->assertUnprocessable();
+ $expired = $this->grant($bootstrap, 'validator');
+ DB::table('portal_role_assignments')->where('id', $expired)->update(['starts_at' => now()->subDays(2), 'expires_at' => now()->subDay()]);
+ $this->assertFalse(app(PortalProfileAccess::class)->has($bootstrap, 'validator'));
+ }
+
+ public function test_role_accumulation_does_not_override_author_auditor_or_state_denials(): void
+ {
+ $user = $this->actor();
+ $this->grant($user, 'promoter');
+ $draft = $this->draft($user);
+ $id = $draft['id'];
+ $this->grant($user, 'validator');
+ $this->grant($user, 'publisher');
+ DB::table('opportunities')->where('id', $id)->update(['status' => 'submitted']);
+ $etag = app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id));
+ $this->mfa($user)->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $etag, 'action' => 'approve', 'reason' => self::REASON])->assertForbidden();
+ $this->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $etag, 'reason' => self::REASON])->assertForbidden();
+ DB::table('opportunities')->where('id', $id)->update(['status' => 'draft']);
+ config(['portal.managers' => [$user->email], 'portal.opportunity_dashboard_access_enabled' => true]);
+ $this->get('/management/opportunities/create')->assertForbidden();
+ $this->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid(), 'title' => 'Legacy bypass'])->assertForbidden();
+ $this->get('/dashboard')->assertInertia(fn (Assert $p) => $p->where('opportunityManagement', null)->where('summary.canCreateOpportunity', false));
+ $this->grant($user, 'auditor');
+ $etag = app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id));
+ $this->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $etag, 'title' => 'forbidden', 'reason' => self::REASON])->assertForbidden();
+ $this->get('/minhas-oportunidades/'.$id.'/view')->assertOk();
+ $this->postJson('/management/sectors', ['name' => 'Auditor bypass'])->assertForbidden();
+ $this->assertSame('QA private opportunity', Opportunity::findOrFail($id)->title);
+ }
+
+ public function test_independent_review_preserves_versions_and_normative_gates_remain_closed(): void
+ {
+ $promoter = $this->actor();
+ $validator = $this->actor();
+ $publisher = $this->actor();
+ $this->grant($promoter, 'promoter');
+ $this->grant($validator, 'validator');
+ $this->grant($publisher, 'publisher');
+ $draft = $this->draft($promoter);
+ $id = $draft['id'];
+ $this->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $draft['etag'], 'action' => 'submit', 'reason' => self::REASON])->assertUnprocessable();
+ $this->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $draft['etag'], 'action' => 'request_archive', 'reason' => self::REASON])->assertOk()->assertJsonPath('status', 'draft');
+ $this->assertNotNull(Opportunity::findOrFail($id)->workflow_context['request_archive']);
+ // Explicit review-state fixture exercises the developing workflow, not a complete submission.
+ $context = Opportunity::findOrFail($id)->workflow_context;
+ $context['working_state'] = 'submitted';
+ DB::table('opportunities')->where('id', $id)->update(['status' => 'submitted', 'workflow_context' => json_encode($context)]);
+ $etag = app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id));
+ $this->actingAs($validator)->withSession(['portal.mfa_actor' => null])->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $etag, 'action' => 'start_review', 'reason' => self::REASON])->assertForbidden();
+ $review = $this->mfa($validator)->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $etag, 'action' => 'start_review', 'reason' => self::REASON])->assertOk()->json();
+ $this->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $review['etag'], 'action' => 'approve', 'reason' => self::REASON])->assertUnprocessable();
+ $correction = $this->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $review['etag'], 'action' => 'request_correction', 'reason' => self::REASON, 'correction_items' => ['summary']])->assertOk()->json();
+ $this->actingAs($promoter)->putJson('/minhas-oportunidades/'.$id.'/draft', ['etag' => $correction['etag'], 'summary' => 'QA correction', 'reason' => self::REASON])->assertOk();
+ $etag = app(OpportunityManagement::class)->etag(Opportunity::findOrFail($id));
+ $this->mfa($publisher)->postJson('/minhas-oportunidades/'.$id.'/workflow', ['etag' => $etag, 'action' => 'publish', 'reason' => self::REASON])->assertConflict();
+ $this->assertSame(0, Opportunity::published()->count());
+ }
+
+ public function test_revocation_invalidates_existing_session_and_legacy_manager_cannot_bypass_scope(): void
+ {
+ $first = $this->actor();
+ $second = $this->actor();
+ $approver = $this->actor();
+ config(['portal_profiles.bootstrap_authorized' => true]);
+ $this->mfa($approver);
+ app(PortalSuperusers::class)->initialize($first, $second, $approver);
+ $promoter = $this->actor();
+ $assignment = $this->grant($promoter, 'promoter');
+ $draft = $this->draft($promoter);
+ $manager = $this->actor();
+ config(['portal.managers' => [$manager->email]]);
+ $this->actingAs($manager)->get('/management/opportunities/'.$draft['id'].'/edit')->assertForbidden();
+ $this->get('/management/opportunities')->assertInertia(fn (Assert $p) => $p->where('records.total', 0));
+ $this->putJson('/api/v1/investment/admin/opportunities/'.$draft['id'].'/context', [])->assertForbidden();
+ $this->getJson('/management/territories/opportunities/'.$draft['id'])->assertForbidden();
+ $this->getJson('/management/territory-subjects?kind=opportunities')->assertJsonCount(0, 'data');
+ $this->postJson('/management/opportunity-origin/preview', ['id' => $draft['id'], 'classification' => 'real', 'reason' => self::REASON])->assertForbidden();
+ $this->mfa($first)->postJson('/perfis/atribuicoes/'.$assignment.'/revogar', ['reason' => self::REASON])->assertOk();
+ $this->actingAs($promoter)->withSession(['portal.access_revision' => 0])->getJson('/minhas-oportunidades/'.$draft['id'].'/view')->assertUnauthorized();
+ $this->assertDatabaseHas('portal_role_assignments', ['id' => $assignment]);
+ $this->assertFalse(app(PortalProfileAccess::class)->has($promoter, 'promoter'));
+ }
+
+ public function test_superuser_pair_is_initialized_once_and_replaced_atomically_with_independent_approval(): void
+ {
+ $first = $this->actor();
+ $second = $this->actor();
+ $approver = $this->actor();
+ $candidate = $this->actor();
+ config(['portal_profiles.bootstrap_authorized' => true]);
+ $this->mfa($approver);
+ $service = app(PortalSuperusers::class);
+ $service->initialize($first, $second, $approver);
+ $service->initialize($first, $second, $approver);
+ $this->assertSame(1, DB::table('portal_superuser_pair')->count());
+ $this->mfa($first)->deleteJson('/user/two-factor-authentication')->assertForbidden();
+ $this->deleteJson('/settings/profile')->assertForbidden();
+ $this->patchJson('/settings/profile', ['email' => 'changed-qa@example.invalid'])->assertForbidden();
+ $this->assertNotNull($first->fresh()->two_factor_secret);
+ try {
+ DB::transaction(fn () => DB::table('portal_superuser_pair')->delete());
+ $this->fail('Removal of the pair must be blocked by PostgreSQL.');
+ } catch (QueryException $error) {
+ $this->assertStringContainsString('Superuser pair cannot be removed', $error->getMessage());
+ }
+ $this->assertSame(1, DB::table('portal_superuser_pair')->count());
+ $this->mfa($first)->postJson('/perfis/atribuicoes', ['user_id' => $candidate->id, 'role' => 'superuser', 'opportunity_types' => ['investment_project'], 'reason' => self::REASON])->assertUnprocessable();
+ $id = $this->postJson('/perfis/substituicoes', ['old_user_id' => $second->id, 'new_user_id' => $candidate->id, 'reason' => self::REASON])->assertCreated()->json('id');
+ $this->postJson('/perfis/seguranca/'.$id.'/aprovar')->assertForbidden();
+ $this->postJson('/perfis/substituicoes/'.$id.'/aplicar')->assertConflict();
+ $this->mfa($second)->postJson('/perfis/seguranca/'.$id.'/aprovar')->assertOk();
+ $this->mfa($first)->postJson('/perfis/substituicoes/'.$id.'/aplicar')->assertOk();
+ $pair = DB::table('portal_superuser_pair')->first();
+ $this->assertSame([$first->id, $candidate->id], [(int) $pair->first_user_id, (int) $pair->second_user_id]);
+ $this->assertFalse(app(PortalProfileAccess::class)->superuser($second));
+ $this->assertSame(1, (int) $second->fresh()->portal_access_revision);
+ $this->postJson('/perfis/substituicoes/'.$id.'/aplicar')->assertConflict();
+ $this->assertSame(1, DB::table('audit_events')->where('action', 'superuser_replaced')->count());
+ }
+}
diff --git a/tests/Feature/PortalProfileInstallationTest.php b/tests/Feature/PortalProfileInstallationTest.php
new file mode 100644
index 00000000..540ec624
--- /dev/null
+++ b/tests/Feature/PortalProfileInstallationTest.php
@@ -0,0 +1,221 @@
+proofDirectory = storage_path('framework/testing/profile-install-'.Str::uuid());
+ mkdir($this->proofDirectory, 0700, true);
+ config(['portal_profiles.proof_directory' => $this->proofDirectory, 'portal.profile_access_enabled' => false]);
+ }
+
+ protected function tearDown(): void
+ {
+ foreach (glob($this->proofDirectory.'/*') ?: [] as $file) {
+ unlink($file);
+ }
+ rmdir($this->proofDirectory);
+ parent::tearDown();
+ }
+
+ private function manager(): User
+ {
+ $user = $this->actor();
+ config(['portal.managers' => [$user->email]]);
+
+ return $user;
+ }
+
+ private function actor(): User
+ {
+ return User::factory()->create(['two_factor_secret' => Crypt::encryptString('JBSWY3DPEHPK3PXP'), 'two_factor_confirmed_at' => now()]);
+ }
+
+ private function login(User $user, bool $mfa = true): static
+ {
+ return $this->actingAs($user)->withSession(['portal.mfa_actor' => $mfa ? $user->id : null, 'portal.mfa_at' => $mfa ? time() : 0]);
+ }
+
+ private function emptySchema(): void
+ {
+ (require database_path('migrations/'.PortalProfileInstallation::MIGRATION.'.php'))->down();
+ DB::table('migrations')->where('migration', PortalProfileInstallation::MIGRATION)->delete();
+ }
+
+ private function data(): array
+ {
+ return ['hash' => $this->getJson('/management/profile-install')->assertOk()->json('hash'), 'confirm' => true,
+ 'idempotency_key' => (string) Str::uuid(), 'reason' => 'Instalação sintética em base isolada de testes'];
+ }
+
+ private function readinessFixture(): void
+ {
+ // Synthetic files exercise validation; they are never deployment backup evidence.
+ file_put_contents($this->proofDirectory.'/dump', 'unit-fixture-not-a-real-dump');
+ file_put_contents($this->proofDirectory.'/files', 'unit-fixture-not-real-files');
+ $target = DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
+ file_put_contents($this->proofDirectory.'/readiness.json', json_encode(['verified_at' => gmdate('c'), 'target' => $target,
+ 'code_hash' => app(PortalProfileInstallation::class)->fingerprint(), 'restore_verified' => true, 'files_verified' => true,
+ 'qa_passed' => true, 'compatibility_verified' => true, 'dump_path' => $this->proofDirectory.'/dump', 'dump_sha256' => hash_file('sha256', $this->proofDirectory.'/dump'),
+ 'files_path' => $this->proofDirectory.'/files', 'files_sha256' => hash_file('sha256', $this->proofDirectory.'/files')], JSON_THROW_ON_ERROR));
+ }
+
+ public function test_cold_install_repetition_empty_reversal_and_reinstallation_preserve_accounts(): void
+ {
+ $actor = $this->manager();
+ $this->emptySchema();
+ $this->assertFalse(Schema::hasColumn('users', 'portal_access_revision'));
+ $this->login($actor);
+ $this->getJson('/management/profile-install')->assertOk()->assertJsonPath('installed', false)->assertJsonPath('consistent', true)->assertJsonPath('ready', false);
+ $this->postJson('/management/profile-install', $this->data())->assertUnprocessable();
+ $this->readinessFixture();
+ $users = DB::table('users')->count();
+ $data = $this->data();
+ $result = $this->postJson('/management/profile-install', $data)->assertOk()->assertJsonPath('changed', true)->json();
+ $this->postJson('/management/profile-install', $data)->assertOk()->assertExactJson($result);
+ $this->postJson('/management/profile-install', [...$data, 'reason' => $data['reason'].' different'])->assertConflict();
+ $this->postJson('/management/profile-install', $this->data())->assertOk()->assertJsonPath('changed', false);
+ $this->assertSame($users, DB::table('users')->count());
+ $this->assertSame(0, DB::table('portal_role_assignments')->count());
+ $this->assertSame(0, DB::table('portal_superuser_pair')->count());
+ $this->assertFalse(config('portal.profile_access_enabled'));
+ $this->assertFalse(config('portal_profiles.authenticated_installation'));
+ $this->assertSame(2, DB::table('audit_events')->where('source_system', 'portal-profile-installation')->count());
+ $this->emptySchema();
+ $this->postJson('/management/profile-install', $this->data())->assertOk()->assertJsonPath('changed', true);
+ }
+
+ public function test_dependencies_integrity_stale_preview_and_partial_schema_fail_closed(): void
+ {
+ $actor = $this->manager();
+ $this->emptySchema();
+ $this->login($actor);
+ $this->readinessFixture();
+ $data = $this->data();
+ file_put_contents($this->proofDirectory.'/dump', 'tampered');
+ $this->postJson('/management/profile-install', $data)->assertConflict();
+ $this->postJson('/management/profile-install', $this->data())->assertUnprocessable();
+ $this->readinessFixture();
+ DB::table('migrations')->where('migration', '2026_10_09_030000_extend_opportunity_resources')->delete();
+ $this->getJson('/management/profile-install')->assertOk()->assertJsonPath('dependencies.resources_030000', false);
+ $this->postJson('/management/profile-install', $this->data())->assertUnprocessable();
+ Schema::table('users', fn ($t) => $t->unsignedBigInteger('portal_access_revision')->default(0));
+ $this->getJson('/management/profile-install')->assertOk()->assertJsonPath('consistent', false);
+ $this->postJson('/management/profile-install', $this->data())->assertConflict();
+ }
+
+ public function test_failed_audit_rolls_back_schema_and_ledger_and_can_retry(): void
+ {
+ $actor = $this->manager();
+ $this->emptySchema();
+ $this->login($actor);
+ $this->readinessFixture();
+ DB::statement("ALTER TABLE audit_events ADD CONSTRAINT qa_reject_profile_install CHECK (source_system <> 'portal-profile-installation')");
+ $this->postJson('/management/profile-install', $this->data())->assertStatus(503);
+ $this->assertFalse(Schema::hasTable('portal_role_assignments'));
+ $this->assertFalse(Schema::hasColumn('users', 'portal_access_revision'));
+ $this->assertFalse(DB::table('migrations')->where('migration', PortalProfileInstallation::MIGRATION)->exists());
+ DB::statement('ALTER TABLE audit_events DROP CONSTRAINT qa_reject_profile_install');
+ $this->postJson('/management/profile-install', $this->data())->assertOk()->assertJsonPath('changed', true);
+ }
+
+ public function test_bootstrap_is_explicit_independent_separate_and_cannot_replace_existing_pair(): void
+ {
+ $actor = $this->manager();
+ $first = $this->actor();
+ $second = $this->actor();
+ $this->login($actor, false);
+ $this->postJson('/management/profile-install', $this->data())->assertForbidden();
+ $this->login($actor);
+ $this->postJson('/management/profile-install/bootstrap', [...$this->data(), 'first_user_id' => $actor->id, 'second_user_id' => $second->id])->assertUnprocessable();
+ $this->postJson('/management/profile-install/bootstrap', [...$this->data(), 'first_user_id' => $first->id, 'second_user_id' => $second->id])->assertOk()->assertJsonPath('holders', [$first->id, $second->id]);
+ $this->getJson('/management/profile-install')->assertForbidden();
+ $this->login($first);
+ $this->getJson('/management/profile-install')->assertOk()->assertJsonPath('bootstrap.initialized', true);
+ $this->postJson('/management/profile-install/bootstrap', [...$this->data(), 'first_user_id' => $first->id, 'second_user_id' => $actor->id])->assertConflict();
+ $this->assertSame(1, DB::table('portal_superuser_pair')->count());
+ $this->assertSame(0, DB::table('portal_role_assignments')->count());
+ $this->assertFalse(config('portal_profiles.bootstrap_authorized'));
+ }
+
+ public function test_auditor_restriction_and_history_prevent_privilege_or_destructive_rollback(): void
+ {
+ $actor = $this->manager();
+ app(PortalProfileAdministration::class)->insertGrant((string) Str::uuid(), $this->actor(), [
+ 'user_id' => $actor->id, 'role' => 'auditor', 'opportunity_types' => [], 'source' => 'unit-synthetic-fixture']);
+ $this->login($actor);
+ $this->getJson('/management/profile-install')->assertForbidden();
+ $this->postJson('/management/profile-install', ['hash' => str_repeat('a', 64), 'confirm' => true, 'idempotency_key' => (string) Str::uuid(), 'reason' => 'Instalação sintética vedada ao Auditor'])->assertForbidden();
+ try {
+ (require database_path('migrations/'.PortalProfileInstallation::MIGRATION.'.php'))->down();
+ $this->fail('Used authorization schema must not be dropped.');
+ } catch (\RuntimeException $e) {
+ $this->assertStringContainsString('Preserve authorization history', $e->getMessage());
+ }
+ $this->assertSame(1, DB::table('portal_role_assignments')->count());
+ $this->assertTrue(Schema::hasColumn('users', 'portal_access_revision'));
+ }
+
+ public function test_rollback_preserves_context_even_without_author_or_grants(): void
+ {
+ DB::table('opportunities')->insert(['reference' => 'QA-rollback-context', 'slug' => 'qa-rollback-context', 'workflow_context' => '{"history":["synthetic-preserve"]}']);
+ try {
+ (require database_path('migrations/'.PortalProfileInstallation::MIGRATION.'.php'))->down();
+ $this->fail('Context must survive rollback even without an owner.');
+ } catch (\RuntimeException $e) {
+ $this->assertSame('Preserve scoped opportunities', $e->getMessage());
+ }
+ $this->assertTrue(Schema::hasColumn('opportunities', 'workflow_context'));
+ $this->assertSame(1, DB::table('opportunities')->whereNotNull('workflow_context')->count());
+ }
+
+ public function test_bootstrap_rejects_unreadable_mfa_and_auditor_candidate_without_creating_pair(): void
+ {
+ $manager = $this->manager();
+ $first = $this->actor();
+ $second = $this->actor();
+ $first->forceFill(['two_factor_secret' => 'synthetic-invalid-ciphertext'])->save();
+ $this->login($manager);
+ $this->postJson('/management/profile-install/bootstrap', [...$this->data(), 'first_user_id' => $first->id, 'second_user_id' => $second->id])->assertUnprocessable();
+ $this->assertSame(0, DB::table('portal_superuser_pair')->count());
+ $first->forceFill(['two_factor_secret' => Crypt::encryptString('JBSWY3DPEHPK3PXP')])->save();
+ app(PortalProfileAdministration::class)->insertGrant((string) Str::uuid(), $manager, [
+ 'user_id' => $first->id, 'role' => 'auditor', 'opportunity_types' => [], 'source' => 'unit-synthetic-fixture']);
+ $this->postJson('/management/profile-install/bootstrap', [...$this->data(), 'first_user_id' => $first->id, 'second_user_id' => $second->id])->assertUnprocessable();
+ $this->assertSame(0, DB::table('portal_superuser_pair')->count());
+ $this->assertFalse(config('portal_profiles.bootstrap_authorized'));
+ }
+
+ public function test_partial_schema_cannot_disable_identity_write_controls_but_recovery_is_accessible(): void
+ {
+ $manager = $this->manager();
+ $before = $manager->two_factor_secret;
+ $this->login($manager);
+ config(['portal.profile_access_enabled' => true]);
+ Schema::table('users', fn ($t) => $t->dropColumn('portal_access_revision'));
+ $this->deleteJson('/user/two-factor-authentication')->assertStatus(503);
+ $this->deleteJson('/settings/profile', ['password' => 'not-a-credential'])->assertStatus(503);
+ $this->assertSame($before, $manager->fresh()->two_factor_secret);
+ $this->getJson('/management/profile-install')->assertOk()->assertJsonPath('consistent', false);
+ $this->postJson('/management/profile-install', $this->data())->assertConflict();
+ $this->post('/logout')->assertRedirect('/');
+ $this->assertGuest();
+ }
+}
diff --git a/tests/Feature/TerritoryGeometryImportTest.php b/tests/Feature/TerritoryGeometryImportTest.php
index e1e2b6fe..9c00bca2 100644
--- a/tests/Feature/TerritoryGeometryImportTest.php
+++ b/tests/Feature/TerritoryGeometryImportTest.php
@@ -145,4 +145,79 @@ class TerritoryGeometryImportTest extends TestCase
$this->assertSame(2, DB::table('geo_geometries')->whereNull('deleted_at')->count());
$this->assertSame(0, DB::table('audit_events')->where('action', 'geometry_import_reversed')->count());
}
+
+ public function test_explicit_maputo_correspondences_preserve_the_catalogue_and_are_bound_to_parent_and_exemplar(): void
+ {
+ $this->setupImport();
+ $country = DB::table('geo_locations')->where('code', 'MZ')->value('id');
+ $hash = config('geometry-correspondences.catalogue_sha256');
+ foreach (config('geometry-correspondences.rows.1') as $entry) {
+ $id = (string) Str::uuid();
+ DB::table('geo_locations')->insert(['id' => $id, 'code' => 'QA-'.$id, 'source_system' => 'cartografia-workbook', 'external_id' => $hash.':'.$id,
+ 'source_code' => $entry['target_source_code'], 'name' => $entry['target_name'], 'location_type' => 'province', 'parent_id' => $country, 'data_classification' => 'internal']);
+ }
+ $before = DB::table('geo_locations')->orderBy('id')->get()->toJson();
+ $plan = $this->getJson('/management/territory-geometry-import?level=1')->assertOk()->assertJsonPath('resolved', 4)->json();
+ $rows = collect($plan['rows'])->filter(fn ($row) => $row['correspondence'] !== null);
+ $this->assertCount(2, $rows);
+ $this->assertSame(2, $rows->where('match_basis', 'explicit_versioned_correspondence')->count());
+ // Change the mapping, not the source: the original preview can no longer be applied.
+ config(['geometry-correspondences.version' => 'changed-qa-version']);
+ $this->postJson('/management/territory-geometry-import', $this->input($plan))->assertConflict();
+ config(['geometry-correspondences.version' => $plan['correspondence_version']]);
+ $result = $this->postJson('/management/territory-geometry-import', $this->input($plan))->assertOk()->assertJsonPath('inserted', 4)->json();
+ $this->assertSame($before, DB::table('geo_locations')->orderBy('id')->get()->toJson());
+ foreach ($rows as $row) {
+ $geometry = DB::table('geo_geometries')->where('external_id', $row['external_id'])->first();
+ $properties = json_decode($geometry->properties, true);
+ $this->assertSame('internal', $geometry->data_classification);
+ $this->assertSame($row['location_id'], $geometry->geo_location_id);
+ $this->assertEquals($row['correspondence'], $properties['correspondence']);
+ $this->assertSame($plan['correspondence_sha256'], $properties['correspondence_sha256']);
+ }
+ $this->assertCount(4, $result['created']);
+ // A matching display name under a foreign parent must never acquire MZ06.
+ DB::table('geo_locations')->where('source_code', '11')->update(['parent_id' => DB::table('geo_locations')->where('code', 'QA-FOREIGN')->value('id')]);
+ $new = $this->getJson('/management/territory-geometry-import?level=1')->assertOk()->json();
+ $city = collect($new['rows'])->firstWhere('external_id', '2019-06-07:adm1:MZ06');
+ $this->assertNull($city['location_id']);
+ $this->assertSame('name_unresolved', $city['status']);
+ config(['geometry-correspondences.source_sha256.1' => str_repeat('a', 64)]);
+ $this->getJson('/management/territory-geometry-import?level=1')->assertStatus(422);
+ }
+
+ public function test_ambiguous_names_remain_pending_without_blocking_independent_unique_matches(): void
+ {
+ $this->setupImport();
+ $location = DB::table('geo_locations')->where('location_type', 'province')->where('parent_id', DB::table('geo_locations')->where('code', 'MZ')->value('id'))->first();
+ DB::table('geo_locations')->insert(['id' => (string) Str::uuid(), 'code' => 'QA-DUPLICATE-NAME', 'name' => $location->name,
+ 'parent_id' => $location->parent_id, 'location_type' => 'province', 'data_classification' => 'internal']);
+ $before = DB::table('geo_locations')->orderBy('id')->get()->toJson();
+ $plan = $this->getJson('/management/territory-geometry-import?level=1')->assertOk()->assertJsonPath('resolved', 1)->json();
+ $ambiguous = collect($plan['rows'])->firstWhere('status', 'ambiguous_name');
+ $this->assertNull($ambiguous['location_id']);
+ $this->assertCount(2, $ambiguous['candidates']);
+ $this->postJson('/management/territory-geometry-import', $this->input($plan))->assertOk()->assertJsonPath('inserted', 1)->assertJsonPath('pending', 10);
+ $this->assertSame($before, DB::table('geo_locations')->orderBy('id')->get()->toJson());
+ $this->assertFalse(DB::table('geo_geometries')->where('geo_location_id', $location->id)->exists());
+ }
+
+ public function test_reversal_preserves_parent_correspondences_needed_by_active_descendant_boundaries(): void
+ {
+ $this->setupImport();
+ $plan = $this->getJson('/management/territory-geometry-import?level=1')->assertOk()->json();
+ $result = $this->postJson('/management/territory-geometry-import', $this->input($plan))->assertOk()->json();
+ $parent = DB::table('geo_geometries')->where('id', $result['created'][0]['id'])->first();
+ $properties = json_decode($parent->properties, true);
+ $provinceCode = $properties['source_properties']['ADM1_PCODE'];
+ $child = (string) Str::uuid();
+ DB::table('geo_locations')->insert(['id' => $child, 'code' => 'QA-'.$child, 'name' => 'Synthetic QA district', 'location_type' => 'district', 'parent_id' => $parent->geo_location_id, 'data_classification' => 'internal']);
+ DB::insert('INSERT INTO geo_geometries(id,source_system,external_id,geo_location_id,geometry_type,geom,properties,data_classification) SELECT ?,?,?,?,geometry_type,geom,?::jsonb,? FROM geo_geometries WHERE id=?',
+ [(string) Str::uuid(), 'ine-cod-ab', '2019-06-07:adm2:'.$provinceCode.'99', $child,
+ json_encode(['source_version' => '2019-06-07', 'source_properties' => ['ADM1_PCODE' => $provinceCode]], JSON_THROW_ON_ERROR), 'internal', $parent->id]);
+ $this->postJson('/management/territory-geometry-import/'.$result['batch_id'].'/reverse',
+ ['idempotency_key' => (string) Str::uuid(), 'reason' => 'Recusar reversão do pai enquanto descendentes QA dependem dele', 'confirm' => true])->assertConflict();
+ $this->assertSame(3, DB::table('geo_geometries')->whereNull('deleted_at')->count());
+ $this->assertSame(0, DB::table('audit_events')->where('action', 'geometry_import_reversed')->count());
+ }
}
diff --git a/tests/Support/SyntheticDocument.php b/tests/Support/SyntheticDocument.php
new file mode 100644
index 00000000..aabf9cd9
--- /dev/null
+++ b/tests/Support/SyntheticDocument.php
@@ -0,0 +1,33 @@
+>',
+ '<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
+ '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 600 100] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>',
+ '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
+ '<< /Length '.strlen($stream)." >>\nstream\n".$stream."\nendstream",
+ ];
+ $pdf = "%PDF-1.4\n% Synthetic QA original\n";
+ $offsets = [];
+ foreach ($objects as $index => $object) {
+ $offsets[] = strlen($pdf);
+ $pdf .= ($index + 1)." 0 obj\n".$object."\nendobj\n";
+ }
+ $xref = strlen($pdf);
+ $pdf .= "xref\n0 6\n0000000000 65535 f \n";
+ foreach ($offsets as $offset) {
+ $pdf .= sprintf('%010d 00000 n ', $offset)."\n";
+ }
+
+ return $pdf."trailer\n<< /Size 6 /Root 1 0 R >>\nstartxref\n".$xref."\n%%EOF\n";
+ }
+}
diff --git a/tools/__pycache__/portal-audit-installation-update.cpython-310.pyc b/tools/__pycache__/portal-audit-installation-update.cpython-310.pyc
new file mode 100644
index 00000000..2387475f
Binary files /dev/null and b/tools/__pycache__/portal-audit-installation-update.cpython-310.pyc differ
diff --git a/tools/__pycache__/portal_profiles_http_session.cpython-310.pyc b/tools/__pycache__/portal_profiles_http_session.cpython-310.pyc
new file mode 100644
index 00000000..2cf52643
Binary files /dev/null and b/tools/__pycache__/portal_profiles_http_session.cpython-310.pyc differ
diff --git a/tools/independent-documents-http-qa.py b/tools/independent-documents-http-qa.py
new file mode 100644
index 00000000..c479c4a6
--- /dev/null
+++ b/tools/independent-documents-http-qa.py
@@ -0,0 +1,120 @@
+"""Land originals and explicit room sharing via QA18097, with real MFA and scan."""
+import base64
+import hashlib
+import json
+import subprocess
+import uuid
+from datetime import datetime, timezone
+from portal_profiles_http_session import Session, PRIVATE, EXPECTED, REASON, actors, events, PHP, ROOT
+
+actors['legacy_manager'] = json.loads((PRIVATE / 'resource-http-actors-private.json').read_text(encoding='utf-8-sig'))['manager']
+path = PRIVATE / 'independent-documents-http-qa.json'
+receipt_path = PRIVATE / 'independent-documents-http-receipts-qa.json'
+receipts = json.loads(receipt_path.read_text(encoding='utf-8-sig')) if receipt_path.exists() else {}
+proof = {'target': EXPECTED, 'started_at': datetime.now(timezone.utc).isoformat(), 'active_writes': 0, 'interface_observed': False, 'land': [], 'room': []}
+
+def save():
+ receipt_path.write_text(json.dumps(receipts, indent=2), encoding='utf-8')
+
+def originals():
+ expression = "require 'tests/Support/SyntheticDocument.php';$i=imagecreatetruecolor(16,16);ob_start();imagepng($i);$p=ob_get_clean();ob_start();imagejpeg($i);$j=ob_get_clean();echo json_encode(['pdf'=>base64_encode(Tests\\Support\\SyntheticDocument::pdf()),'png'=>base64_encode($p),'jpg'=>base64_encode($j)]);"
+ value = subprocess.check_output([PHP, '-d', 'extension=C:/Users/macbook/.config/investmoz/php-8.5.11/ext/php_gd.dll', '-r', expression], cwd=ROOT)
+ return [(kind, mime, base64.b64decode(data)) for (kind, data), mime in zip(json.loads(value).items(), ['application/pdf', 'image/png', 'image/jpeg'])]
+
+try:
+ owner = Session('promoter').login()
+ candidate = Session('colleague').login()
+ outsider = Session('outsider').login()
+ manager = Session('legacy_manager').login()
+ files = originals()
+ if 'case_id' not in receipts:
+ result = owner.call('POST', '/investidor/terra-duat', {'payload': {'full_name': 'Synthetic QA document consumer', 'country': 'MZ', 'declared_origin_country_code': 'PT'}}, status=201)
+ receipts['case_id'] = result['id']; save()
+ base = '/investidor/terra-duat/' + receipts['case_id']
+ def case():
+ response = owner.call('GET', base, inertia=True)
+ return response.get('props', response)
+ for kind, mime, data in files:
+ name = 'qa-consumer-original.' + kind
+ page = case()
+ existing = next((d for d in page['documents'] if d['file_name'] == name), None)
+ if existing is None:
+ owner.call('POST', base + '/documentos', {'version': page['case']['version'], 'category': 'other'}, multipart=(name, mime, data), status=201)
+ existing = next(d for d in case()['documents'] if d['file_name'] == name)
+ url = base + '/documentos/' + existing['id']
+ original = owner.call('GET', url, binary=True)
+ assert original == data
+ manager.call('GET', url, status=404, binary=True)
+ outsider.call('GET', url, status=404, binary=True)
+ proof['land'].append({'type': kind, 'attachment_id': existing['id'], 'sha256': hashlib.sha256(data).hexdigest(), 'owner': 21, 'manager_private_route_denied': 404, 'other_owner_denied': 404})
+ print_page = owner.call('GET', base + '/imprimir', inertia=True)
+ assert print_page['component'] == 'land-assistance/print' and 'Não constitui' in print_page['props']['disclaimer']
+ fresh = Session('promoter').login()
+ response = fresh.call('GET', base, inertia=True)
+ restored = response.get('props', response)
+ assert restored['case']['payload']['country'] == 'MZ'
+ assert restored['case']['payload']['declared_origin_country_code'] == 'PT'
+ for row, (_, _, data) in zip(proof['land'], files):
+ assert fresh.call('GET', base + '/documentos/' + row['attachment_id'], binary=True) == data
+ proof['land_print'] = {'inertia_template_recovered': True, 'pdf_generated_by_browser': False, 'new_mfa_recovery': True, 'country_origin_recovered': ['MZ', 'PT']}
+ if 'offer_id' not in receipts:
+ draft = owner.call('POST', '/parcerias/rascunhos', {'client_key': str(uuid.uuid4()), 'title': 'Synthetic QA document sharing only', 'kind': 'seeking', 'partnership_type': 'joint_venture', 'offer': 'Synthetic QA capacity', 'seeking': 'Synthetic QA contribution', 'payload': {'summary': 'Synthetic QA; no actual undertaking', 'consent': True}, 'origins': [], 'locations': []})
+ receipts['offer_id'] = draft['id']; save()
+ offer_base = '/parcerias/' + str(receipts['offer_id'])
+ offer = owner.call('GET', offer_base)['record']
+ if offer['status'] == 'draft':
+ owner.call('POST', offer_base + '/estado', {'version': offer['version'], 'action': 'submit', 'reason': REASON})
+ offer = owner.call('GET', offer_base)['record']
+ if offer['status'] != 'published':
+ manager.call('POST', offer_base + '/estado', {'version': offer['version'], 'action': 'publish', 'reason': REASON})
+ if 'interest_id' not in receipts:
+ interest = candidate.call('POST', offer_base + '/interesses', {'proposal': 'Synthetic QA sharing request', 'payload': {'consent': True}})
+ receipts['interest_id'] = interest['id']; save()
+ interest = next(i for i in owner.call('GET', offer_base)['interests'] if i['id'] == receipts['interest_id'])
+ for action in ['shortlist', 'connect']:
+ if interest.get('room_id'):
+ break
+ if action == 'shortlist' and interest['status'] not in ['submitted', 'clarification']:
+ continue
+ owner.call('POST', '/parcerias/candidaturas/' + str(interest['id']), {'version': interest['version'], 'action': action, 'reason': REASON})
+ interest = next(i for i in owner.call('GET', offer_base)['interests'] if i['id'] == receipts['interest_id'])
+ receipts['room_id'] = interest['room_id']; save()
+ room_base = '/parcerias/salas/' + str(receipts['room_id'])
+ for kind, mime, data in files:
+ name = 'qa-room-original.' + kind
+ current = owner.call('GET', room_base)
+ row = next((d for d in current['documents'] if d['file_name'] == name), None)
+ if row is None:
+ owner.call('POST', room_base + '/documentos', {'shared': 0}, multipart=(name, mime, data))
+ row = next(d for d in owner.call('GET', room_base)['documents'] if d['file_name'] == name)
+ url = room_base + '/documentos/' + str(row['id'])
+ if row['shared']:
+ owner.call('POST', url + '/partilha', {'shared': False})
+ assert owner.call('GET', url, binary=True) == data
+ candidate.call('GET', url, status=404, binary=True)
+ candidate.call('POST', url + '/partilha', {'shared': True}, status=403)
+ owner.call('POST', url + '/partilha', {'shared': True})
+ assert candidate.call('GET', url, binary=True) == data
+ manager.call('GET', url, status=403, binary=True)
+ outsider.call('GET', url, status=403, binary=True)
+ fresh_candidate = Session('colleague').login()
+ assert fresh_candidate.call('GET', url, binary=True) == data
+ owner.call('POST', url + '/partilha', {'shared': False})
+ fresh_candidate.call('GET', url, status=404, binary=True)
+ assert all(d['id'] != row['id'] for d in fresh_candidate.call('GET', room_base)['documents'])
+ assert owner.call('GET', url, binary=True) == data
+ proof['room'].append({'type': kind, 'attachment_id': row['id'], 'sha256': hashlib.sha256(data).hexdigest(), 'private_candidate': 404,
+ 'share_change_by_non_author': 403, 'explicit_share_recovered': True, 'new_mfa_session': True, 'share_revoked': 404,
+ 'manager_non_participant': 403, 'outsider': 403, 'original_preserved': True})
+ proof['result'] = 'passed'
+except Exception as error:
+ proof.update({'result': 'failed', 'failure': str(error)})
+ raise
+finally:
+ proof['events'] = events
+ proof['receipts'] = receipts
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ if path.exists():
+ path.rename(PRIVATE / ('independent-documents-http-qa-' + datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') + '.json'))
+ path.write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'result': proof['result'], 'target': EXPECTED, 'land_types': len(proof['land']), 'room_types': len(proof['room']), 'events': len(events), 'active_writes': 0}))
diff --git a/tools/independent-documents-verify-qa.php b/tools/independent-documents-verify-qa.php
new file mode 100644
index 00000000..cfd0903e
--- /dev/null
+++ b/tools/independent-documents-verify-qa.php
@@ -0,0 +1,54 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$private = storage_path('app/private/investmoz-v2/portal-audit');
+$http = json_decode(file_get_contents($private.'/independent-documents-http-qa.json'), true, 512, JSON_THROW_ON_ERROR);
+if ($http['result'] !== 'passed' || $http['target'] !== $target['database'].':'.$target['port']) {
+ throw new RuntimeException('Successful HTTP proof for this QA target required.');
+}
+$proof = DB::transaction(function () use ($http, $target): array {
+ DB::statement('SET TRANSACTION READ ONLY');
+ $documents = [];
+ foreach (['land' => 'land_assistance_documents', 'room' => 'partnership_documents'] as $scope => $table) {
+ foreach ($http[$scope] as $row) {
+ $link = DB::table($table)->where('id', $row['attachment_id'])->first();
+ $document = DB::table('documents')->where('id', $link->document_id)->first();
+ $bytes = Storage::disk('local')->get($document->storage_key);
+ if ($document->storage_encryption === 'laravel') {
+ $bytes = Crypt::decryptString($bytes);
+ }
+ $scan = DB::table('document_malware_scans')->where('document_id', $document->id)->where('result', 'clean')->exists();
+ $valid = $document->status === 'active' && $document->malware_scan_status === 'clean'
+ && $document->malware_engine === 'ClamAV' && $document->malware_signatures_at !== null && $scan
+ && trim($document->sha256) === $row['sha256'] && $document->malware_scanned_sha256 === $row['sha256']
+ && hash('sha256', $bytes) === $row['sha256'] && strlen($bytes) === $document->size_bytes
+ && $document->uploaded_by === 21 && ($scope !== 'room' || ! $link->shared);
+ if (! $valid) {
+ throw new RuntimeException('Original/scan/permission evidence mismatch: '.$scope.'/'.$row['type']);
+ }
+ $documents[] = ['scope' => $scope, 'type' => $row['type'], 'document_id' => $document->id,
+ 'sha256' => $row['sha256'], 'engine' => $document->malware_engine, 'signatures_at' => $document->malware_signatures_at,
+ 'scanned_hash_matches_original' => true, 'original_bytes_preserved' => true, 'encrypted' => $document->storage_encryption === 'laravel'];
+ }
+ }
+ $events = DB::table('partnership_events')->where('partnership_id', $http['receipts']['offer_id'])
+ ->where('event_type', 'partnership.document_sharing_changed.v1')->count();
+ if (count($documents) !== 6 || $events < 6) {
+ throw new RuntimeException('Expected six originals and six explicit sharing transitions.');
+ }
+
+ return ['result' => 'passed', 'target' => $target, 'captured_at' => gmdate('c'), 'documents' => $documents,
+ 'sharing_audit_events' => $events, 'active_writes' => 0, 'interface_observed' => false];
+});
+file_put_contents($private.'/independent-documents-verification-qa.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode(['result' => $proof['result'], 'documents' => count($proof['documents']), 'sharing_audit_events' => $proof['sharing_audit_events'], 'active_writes' => 0], JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/opportunity-contract-inspect-qa.php b/tools/opportunity-contract-inspect-qa.php
new file mode 100644
index 00000000..580d82da
--- /dev/null
+++ b/tools/opportunity-contract-inspect-qa.php
@@ -0,0 +1,23 @@
+make(Kernel::class)->bootstrap();
+$identity = portalQaAssertTarget($target);
+DB::beginTransaction();
+DB::statement('SET TRANSACTION READ ONLY');
+$result = ['target' => $identity];
+foreach (['sectors', 'economic_activities', 'reference_catalog_versions', 'contacts', 'investors', 'organizations', 'tasks', 'documents', 'opportunity_location_drafts'] as $table) {
+ $result[$table] = ['columns' => Schema::getColumnListing($table), 'count' => DB::table($table)->count()];
+}
+$result['activities'] = DB::table('economic_activities')->orderBy('code')->get(['id', 'parent_id', 'sector_id', 'code', 'label_pt_mz', 'status', 'catalog_version_id'])->all();
+file_put_contents($root.'/storage/app/private/investmoz-v2/portal-audit/opportunity-contract-inspect-qa.json', json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+DB::rollBack();
+echo json_encode(['target' => $identity, 'counts' => array_map(fn ($v) => is_array($v) ? ($v['count'] ?? count($v)) : null, $result), 'active_writes' => 0]).PHP_EOL;
diff --git a/tools/opportunity-office-documents-http-qa.py b/tools/opportunity-office-documents-http-qa.py
new file mode 100644
index 00000000..6ed8d77d
--- /dev/null
+++ b/tools/opportunity-office-documents-http-qa.py
@@ -0,0 +1,90 @@
+"""Synthetic OOXML originals through the guarded QA web server; no secrets in proof."""
+import hashlib
+import io
+import json
+import uuid
+import zipfile
+import xml.etree.ElementTree as ET
+from datetime import datetime, timezone
+from portal_profiles_http_session import Session, PRIVATE, EXPECTED, REASON, events
+
+source = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text(encoding='utf-8-sig'))
+assert source['result'] == 'passed' and source['target'] == EXPECTED
+record = next(c['id'] for c in source['cases'] if c['category'] == 'concession')
+base = f'/minhas-oportunidades/{record}'
+proof = {'target': EXPECTED, 'id': record, 'started_at': datetime.now(timezone.utc).isoformat(), 'active_writes': 0, 'interface_observed': False, 'types': []}
+
+def file_bytes(kind):
+ mime = 'application/vnd.openxmlformats-officedocument.' + ('wordprocessingml.document' if kind == 'docx' else 'spreadsheetml.sheet')
+ part = 'word/document.xml' if kind == 'docx' else 'xl/workbook.xml'
+ content = ('Synthetic QA no official value ' if kind == 'docx' else ' ')
+ files = {
+ '[Content_Types].xml': f' ' + (' ' if kind == 'xlsx' else '') + ' ',
+ '_rels/.rels': f' ',
+ part: content,
+ }
+ if kind == 'xlsx':
+ files['xl/_rels/workbook.xml.rels'] = ' '
+ files['xl/worksheets/sheet1.xml'] = 'Synthetic QA no official value |
'
+ buffer = io.BytesIO()
+ with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as z:
+ for name, text in files.items():
+ ET.fromstring(text)
+ z.writestr(name, text)
+ with zipfile.ZipFile(io.BytesIO(buffer.getvalue())) as z:
+ assert z.testzip() is None and z.read(part).decode() == content
+ return mime, buffer.getvalue()
+
+def page(s):
+ return s.call('GET', base + '/edit', inertia=True)['props']
+
+def resources(s):
+ return s.call('GET', base + '/resources', inertia=True)['props']['resources']['documents']
+
+try:
+ owner = Session('promoter').login()
+ reviewer = Session('validator').login()
+ publisher = Session('publisher').login()
+ outsider = Session('outsider').login()
+ for kind in ['docx', 'xlsx']:
+ mime, data = file_bytes(kind)
+ title = 'Original sintético QA OOXML ' + kind
+ old = next((r for r in resources(owner) if r['payload'].get('title') == title), None)
+ if old:
+ assert old['deleted_at'] is None
+ resource_id = old['id']
+ data = owner.call('GET', base + f'/resources/documents/{resource_id}/download', binary=True)
+ with zipfile.ZipFile(io.BytesIO(data)) as z:
+ assert z.testzip() is None
+ for name in z.namelist():
+ ET.fromstring(z.read(name))
+ else:
+ resource_id = owner.call('POST', base + '/resources/documents', {'etag': page(owner)['etag'], 'creation_key': str(uuid.uuid4()), 'reason': REASON,
+ 'payload': json.dumps({'title': title, 'category': 'qa-synthetic', 'classification': 'restricted', 'visibility': 'internal'})},
+ multipart=('synthetic-qa.' + kind, mime, data), status=201)['id']
+ row = next(r for r in resources(owner) if r['id'] == resource_id)
+ digest = hashlib.sha256(data).hexdigest()
+ assert row['file']['media_type'] == mime and row['file']['malware_scan_status'] == 'clean' and row['file']['sha256'].strip() == digest
+ url = base + f'/resources/documents/{resource_id}/download'
+ for actor in [owner, reviewer, publisher]:
+ assert actor.call('GET', url, binary=True) == data
+ outsider.call('GET', url, status=403, binary=True)
+ for action in ['delete', 'restore']:
+ current = next(r for r in resources(owner) if r['id'] == resource_id)
+ owner.call('POST', base + f'/resources/documents/{resource_id}/lifecycle', {'etag': page(owner)['etag'], 'version': current['version'], 'action': action, 'reason': REASON, 'confirm': True})
+ if action == 'delete':
+ owner.call('GET', url, status=404, binary=True)
+ assert resource_id not in [d['id'] for d in page(owner)['canonicalOptions']['resources']['documents']]
+ fresh = Session('promoter').login()
+ assert fresh.call('GET', url, binary=True) == data
+ proof['types'].append({'type': kind, 'resource_id': resource_id, 'sha256': digest, 'package_xml_crc_valid': True, 'clamd_real_clean': True,
+ 'allowed': [21, 24, 25], 'foreign_organization': 403, 'deleted_download': 404, 'original_restored_identical_new_session': True})
+ proof['result'] = 'passed'
+except Exception as error:
+ proof.update({'result': 'failed', 'failure': str(error)})
+ raise
+finally:
+ proof['events'] = events
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ (PRIVATE / 'opportunity-office-documents-http-qa.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'result': proof['result'], 'target': EXPECTED, 'types': [r['type'] for r in proof['types']], 'events': len(events), 'active_writes': 0}))
diff --git a/tools/opportunity-resources-qa.php b/tools/opportunity-resources-qa.php
index f363de56..3ac9361f 100644
--- a/tools/opportunity-resources-qa.php
+++ b/tools/opportunity-resources-qa.php
@@ -43,7 +43,40 @@ if (! is_dir($sessions)) {
mkdir($sessions, 0700, true);
}
config(['session.files' => $sessions]);
+config(['portal.opportunity_dashboard_access_enabled' => true, 'portal.qa_build_directory' => 'build-qa-opportunities']);
+config(['portal.opportunity_specialized_drafts_enabled' => true]);
+config(['portal.profile_access_enabled' => true]);
+// QA-only bootstrap ceremony: fixed synthetic identities, normal authenticated MFA.
+Illuminate\Support\Facades\Route::middleware(['web', 'auth', 'verified', \App\Http\Middleware\EnsurePortalProfiles::class])->post('/qa-auditoria/perfis/inicializar', function (Request $request) use ($dir) {
+ $actors = json_decode(file_get_contents($dir.'/portal-audit/profiles-v1-actors-private.json'), true, 512, JSON_THROW_ON_ERROR);
+ abort_unless($request->user()->id === $actors['bootstrap']['id'], 403);
+ config(['portal_profiles.bootstrap_authorized' => true]);
+ try {
+ app(\App\Services\PortalSuperusers::class)->initialize(User::findOrFail($actors['super_first']['id']), User::findOrFail($actors['super_second']['id']), $request->user());
+ } finally {
+ config(['portal_profiles.bootstrap_authorized' => false]);
+ }
+ return response()->json(['initialized' => true, 'holders' => [$actors['super_first']['id'], $actors['super_second']['id']]]);
+});
+// Read-only report derived from the sole audit matrix, accessible only on QA.
+function authorizeQaAuditReader(Request $request): void
+{
+ $access = app(\App\Services\PortalProfileAccess::class);
+ abort_unless($request->user()->can('manage-portal') || $access->has($request->user(), 'auditor') || ($access->superuser($request->user()) && $access->mfa($request->user())), 403);
+}
+Illuminate\Support\Facades\Route::middleware(['web', 'auth', 'verified'])->get('/qa-auditoria/pedidos-abertos', function (Request $request) use ($dir) {
+ authorizeQaAuditReader($request);
+ return response()->file($dir.'/portal-audit/pedidos-abertos.html', ['Cache-Control' => 'private, no-store']);
+});
+foreach (['relatorio-executivo', 'backlog', 'perfis-v1-reconciliacao', 'roteiro-manual-perfis-v1'] as $reportName) {
+ Illuminate\Support\Facades\Route::middleware(['web', 'auth', 'verified'])->get('/qa-auditoria/'.$reportName, function (Request $request) use ($root, $reportName) {
+ authorizeQaAuditReader($request);
+ $content = file_get_contents($root.'/docs/investmoz/v2/auditoria-portal/'.$reportName.'.md');
+ return response('InvestMoz — '.$reportName.' '.htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8').' ')->header('Cache-Control', 'private, no-store');
+ });
+}
Vite::useHotFile($root.'/storage/framework/qa-opportunity-resources-hot-absent');
+Vite::useBuildDirectory('build-qa-opportunities');
if (PHP_SAPI === 'cli' && ($argv[1] ?? '') === 'prepare') {
$migration = require $root.'/database/migrations/'.OpportunityResourceInstallation::MIGRATION.'.php';
$migration->up();
diff --git a/tools/opportunity-semantic-documents-http-qa.py b/tools/opportunity-semantic-documents-http-qa.py
new file mode 100644
index 00000000..1150f0a4
--- /dev/null
+++ b/tools/opportunity-semantic-documents-http-qa.py
@@ -0,0 +1,89 @@
+"""Real PDF lifecycle and scoped downloads on QA18097; sanitized receipts only."""
+import base64
+import hashlib
+import json
+import subprocess
+import uuid
+import io
+import sys
+from datetime import datetime, timezone
+from portal_profiles_http_session import Session, PRIVATE, EXPECTED, REASON, events, PHP, ROOT
+sys.path.insert(0, str(PRIVATE / 'pdf-proof-tooling'))
+import pypdf
+
+source = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text())
+assert source['result'] == 'passed' and source['target'] == EXPECTED
+record_id = next(c['id'] for c in source['cases'] if c['category'] == 'concession')
+path = PRIVATE / 'opportunity-semantic-documents-http-qa.json'
+proof = {'target': EXPECTED, 'id': record_id, 'started_at': datetime.now(timezone.utc).isoformat(),
+ 'active_writes': 0, 'interface_demonstrated': False}
+
+
+def page(s):
+ return s.call('GET', f'/minhas-oportunidades/{record_id}/edit', inertia=True)['props']
+
+
+def resources(s):
+ return s.call('GET', f'/minhas-oportunidades/{record_id}/resources', inertia=True)['props']['resources']
+
+
+try:
+ promoter = Session('promoter').login()
+ label = 'Synthetic QA PDF - no official or legal value - ' + str(uuid.uuid4())
+ expression = "require 'tests/Support/SyntheticDocument.php';echo base64_encode(Tests\\Support\\SyntheticDocument::pdf('" + label + "'));"
+ data = base64.b64decode(subprocess.check_output([PHP, '-r', expression], cwd=ROOT))
+ reader = pypdf.PdfReader(io.BytesIO(data), strict=True)
+ assert len(reader.pages) == 1 and label in reader.pages[0].extract_text()
+ existing = next((d for d in resources(promoter)['documents'] if d['payload'].get('title') == 'PDF sintético QA válido — sem valor oficial'), None)
+ if existing and existing['deleted_at'] is not None:
+ promoter.call('POST', f"/minhas-oportunidades/{record_id}/resources/documents/{existing['id']}/lifecycle", {
+ 'etag': page(promoter)['etag'], 'version': existing['version'], 'action': 'restore', 'reason': REASON, 'confirm': True})
+ uploaded = {'id': existing['id']} if existing else promoter.call('POST', f'/minhas-oportunidades/{record_id}/resources/documents', {
+ 'etag': page(promoter)['etag'], 'creation_key': str(uuid.uuid4()), 'reason': REASON,
+ 'payload': json.dumps({'title': 'PDF sintético QA válido — sem valor oficial', 'category': 'qa-synthetic',
+ 'classification': 'restricted', 'visibility': 'internal'})
+ }, multipart=data, status=201)
+ document_id = uploaded['id']
+ proof['document_resource_id'] = document_id
+ if existing:
+ data = promoter.call('GET', f'/minhas-oportunidades/{record_id}/resources/documents/{document_id}/download', binary=True)
+ reader = pypdf.PdfReader(io.BytesIO(data), strict=True)
+ assert len(reader.pages) == 1 and 'no official or legal value' in reader.pages[0].extract_text()
+ row = next(d for d in resources(promoter)['documents'] if d['id'] == document_id)
+ digest = hashlib.sha256(data).hexdigest()
+ assert row['file']['media_type'] == 'application/pdf' and row['file']['malware_scan_status'] == 'clean'
+ assert row['file']['sha256'].strip() == digest
+ url = f'/minhas-oportunidades/{record_id}/resources/documents/{document_id}/download'
+ assert promoter.call('GET', url, binary=True) == data
+ for key in ['validator', 'publisher']:
+ assert Session(key).login().call('GET', url, binary=True) == data
+ outsider = Session('outsider').login()
+ outsider.call('GET', url, status=403, binary=True)
+ outsider.call('POST', f'/minhas-oportunidades/{record_id}/resources/documents/{document_id}/lifecycle', {
+ 'etag': page(promoter)['etag'], 'version': row['version'], 'action': 'delete', 'reason': REASON, 'confirm': True}, status=403)
+ promoter.call('POST', f'/minhas-oportunidades/{record_id}/resources/documents/{document_id}/lifecycle', {
+ 'etag': page(promoter)['etag'], 'version': row['version'], 'action': 'delete', 'reason': REASON, 'confirm': True})
+ deleted = next(d for d in resources(promoter)['documents'] if d['id'] == document_id)
+ assert deleted['deleted_at'] is not None
+ assert document_id not in [d['id'] for d in page(promoter)['canonicalOptions']['resources']['documents']]
+ promoter.call('GET', url, status=404, binary=True)
+ promoter.call('POST', f'/minhas-oportunidades/{record_id}/resources/documents/{document_id}/lifecycle', {
+ 'etag': page(promoter)['etag'], 'version': deleted['version'], 'action': 'restore', 'reason': REASON, 'confirm': True})
+ new_session = Session('promoter').login()
+ assert new_session.call('GET', url, binary=True) == data
+ restored = next(d for d in resources(new_session)['documents'] if d['id'] == document_id)
+ assert restored['deleted_at'] is None and restored['file']['sha256'].strip() == digest
+ assert document_id in [d['id'] for d in page(new_session)['canonicalOptions']['resources']['documents']]
+ proof.update({'result': 'passed', 'document_resource_id': document_id, 'media_type': 'application/pdf',
+ 'strict_parse': True, 'pages': 1, 'sha256': digest, 'clamd_real_clean': True,
+ 'download_allowed_profiles': [21, 24, 25], 'foreign_organization_download': 403, 'foreign_organization_delete': 403,
+ 'deleted_download': 404, 'inactive_not_offered_by_editor': True, 'restored_original_identical': True,
+ 'recovered_in_new_mfa_session': True})
+except Exception as error:
+ proof.update({'result': 'failed', 'failure': str(error)})
+ raise
+finally:
+ proof['events'] = events
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ path.write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({k: proof[k] for k in ['result', 'target', 'id', 'clamd_real_clean', 'restored_original_identical', 'active_writes']}))
diff --git a/tools/opportunity-semantic-environment-qa.php b/tools/opportunity-semantic-environment-qa.php
new file mode 100644
index 00000000..754fa287
--- /dev/null
+++ b/tools/opportunity-semantic-environment-qa.php
@@ -0,0 +1,21 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$name = '2026_10_09_190000_prepare_investor_path';
+$columns = ['investor_journeys.path_definition_id' => Schema::hasColumn('investor_journeys', 'path_definition_id'), 'journey_steps.path_detail' => Schema::hasColumn('journey_steps', 'path_detail')];
+$definitions = DB::table('questionnaire_versions')->where('code', 'investor-path-19')->get(['id', 'status', 'schema_snapshot'])->map(fn ($r) => ['id' => $r->id, 'status' => $r->status, 'sha256' => hash('sha256', $r->schema_snapshot)])->all();
+$proof = ['captured_at' => gmdate('c'), 'target' => $target, 'active_writes' => 0, 'migration' => $name,
+ 'ledger' => DB::table('migrations')->where('migration', $name)->exists(), 'columns' => $columns, 'definitions' => $definitions,
+ 'resources_030000' => DB::table('migrations')->where('migration', '2026_10_09_030000_extend_opportunity_resources')->exists(),
+ 'profiles_040000' => DB::table('migrations')->where('migration', '2026_10_10_040000_create_portal_profile_authorization')->exists(),
+ 'authorities' => DB::table('authorities')->where('status', 'published')->get(['id', 'label_pt_mz'])->all()];
+file_put_contents(dirname(__DIR__).'/storage/app/private/investmoz-v2/portal-audit/opportunity-semantic-environment-qa.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode($proof, JSON_THROW_ON_ERROR);
diff --git a/tools/opportunity-semantic-fixtures-qa.php b/tools/opportunity-semantic-fixtures-qa.php
new file mode 100644
index 00000000..8b7629b2
--- /dev/null
+++ b/tools/opportunity-semantic-fixtures-qa.php
@@ -0,0 +1,22 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$dir=dirname(__DIR__).'/storage/app/private/investmoz-v2/portal-audit';
+$fixture=json_decode(file_get_contents($dir.'/opportunity-workflow-fixtures-qa.json'),true,512,JSON_THROW_ON_ERROR);
+$version=DB::table('economic_activities')->where('id',$fixture['activity_id'])->value('catalog_version_id');
+$existing=DB::table('authorities')->where('catalog_version_id',$version)->where('code','QA-OP-SEMANTIC')->first();
+$id=$existing?->id ?? (string)Str::uuid();
+if(!$existing)DB::table('authorities')->insert(['id'=>$id,'catalog_version_id'=>$version,'organization_id'=>$fixture['organization_id'],
+ 'code'=>'QA-OP-SEMANTIC','authority_type'=>'qa-synthetic','label_pt_mz'=>'Entidade emissora sintética QA — sem competência real',
+ 'source_reference'=>'Synthetic QA fixture only; not an official source or authority','valid_from'=>'2026-01-01','status'=>'published']);
+$proof=['target'=>$target,'active_writes'=>0,'authority_id'=>$id,'source'=>'QA-synthetic; never import into active data','created'=>$existing===null];
+file_put_contents($dir.'/opportunity-semantic-fixtures-qa.json',json_encode($proof,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
+echo json_encode($proof,JSON_THROW_ON_ERROR);
diff --git a/tools/opportunity-semantic-http-qa.py b/tools/opportunity-semantic-http-qa.py
new file mode 100644
index 00000000..e5a300c2
--- /dev/null
+++ b/tools/opportunity-semantic-http-qa.py
@@ -0,0 +1,109 @@
+"""Per-category live QA semantics, resource permissions and internal workflow. No visual claim."""
+import importlib.util
+import json
+import uuid
+import copy
+from datetime import datetime, timezone
+from pathlib import Path
+
+spec=importlib.util.spec_from_file_location('opportunity_workflow_http_qa',Path(__file__).with_name('opportunity-workflow-http-qa.py'))
+m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
+m.path=m.PRIVATE/'opportunity-semantic-http-qa.json'
+proof=m.proof
+authority=json.loads((m.PRIVATE/'opportunity-semantic-fixtures-qa.json').read_text())['authority_id']
+
+def enrich(p,doc):
+ p['currency']='MZN';p['review_due_date']='2027-01-01'
+ if p['opportunity_category']=='investment_project':
+ p['markets'][0]['country_code']='FR'
+ for i,row in enumerate(p['milestones']):
+ row.update({'start_date':row['due_date'],'end_date':row['due_date'],'responsible_name':'Responsável declarado sintético QA','dependencies':[] if i==0 else [p['milestones'][0]['title']]})
+ if 'real_estate' in p:
+ p['real_estate'].update({'title_document_id':doc,'title_holder_name':'Titular sintético da organização QA','issuing_authority_id':authority,
+ 'utilities':[{'type':t,'status':'existing'} for t in ['electricity','water','sanitation','telecommunications','access']]})
+ if 'land_rights' in p:
+ p['land_rights'].update({'holder_document_id':doc,'communities_affected':False,'exploitation_plan_required':False})
+ if 'business_transaction' in p:
+ bt=p['business_transaction'];bt.update({'available_financial_years':3,'entity_registration':{'tax_identifier':'QA-SYNTHETIC','registration_number':'QA-ONLY','legal_document_id':doc,'beneficial_owner_document_id':doc},
+ 'financial_periods':[{'year':y,'currency':'MZN','revenue':500,'profit':50,'assets':300,'liabilities':100,'cash_flow':50,'document_id':doc} for y in [2023,2024,2025]],
+ 'assets_liabilities':{'assets':'Ativos sintéticos QA','excluded_assets':'Nenhum no ensaio','liabilities':'Passivos sintéticos QA','guarantees':'Nenhuma no ensaio','reconciliation_document_id':doc},
+ 'employees':{'total':2,'contracts':'Vínculos sintéticos','obligations':'Obrigações sintéticas','labor_liabilities':'Nenhum passivo no cenário sintético'},
+ 'contracts_licenses':[{'name':'Licença fictícia QA','transferability':'transferable','expiry_date':'2027-12-31','document_id':doc}],
+ 'litigation_contingencies':[{'type':'none'}]})
+ bt['valuation'].update({'appraiser':'Avaliador sintético QA','document_id':doc})
+ if 'governance_rights' in bt:bt['governance_rights'].update({'board':'Conselho sintético','reserved_matters':'Matérias reservadas sintéticas','dividends':'Dividendos sintéticos','exit':'Saída sintética','deadlock':'Mecanismo sintético de impasse'})
+ if 'partner_contribution' in bt:bt['partner_contribution'].update({'assets':'Ativos sintéticos','technology':'Tecnologia sintética','market':'Mercado sintético','management':'Gestão sintética'})
+ if 'franchise_terms' in bt:bt['franchise_terms'].update({'initial_fee':1000,'royalties':'Encargos sintéticos descritos','support':'Suporte sintético','exclusivity':'Sem exclusividade no cenário','renewal':'Renovação sintética','termination':'Rescisão sintética','brand_license_document_id':doc})
+ return p
+
+def negative(id,p,path,change):
+ bad=copy.deepcopy(p);change(bad);m.save(m.promoter,id,bad)
+ response=m.transition(m.promoter,id,'submit',status=422)
+ assert path in response['errors'],(path,list(response.get('errors',{})))
+ recovered=m.page(m.Session('promoter').login(),id)
+ assert recovered['values']['canonical']==m.normalized(bad)
+ proof.setdefault('negative_fields',[]).append({'id':id,'field':path,'status':422,'incomplete_draft_recovered':True})
+
+try:
+ # Normal administrator assignment; synthetic reviewer, no real institutional responsibility inferred.
+ assignments=m.superuser.call('GET','/perfis/gestao',inertia=True)['props']['assignments']
+ if not any(g['user_id']==m.actors['bootstrap']['id'] and g['role']=='validator' and g['revoked_at'] is None and 'technical_reviewer' in json.loads(g['responsibilities']) and set(m.types).issubset(json.loads(g['opportunity_types'])) for g in assignments):
+ m.superuser.call('POST','/perfis/atribuicoes',{'user_id':m.actors['bootstrap']['id'],'role':'validator','opportunity_types':m.types,
+ 'responsibilities':['technical_reviewer','legal_reviewer','appeal_reviewer'],'reason':'Responsabilidades sintéticas QA para pareceres; nenhuma competência real atribuída'},status=201)
+ reviewer=m.Session('bootstrap').login()
+ for category in m.types:
+ id,p,doc=m.create(category)
+ case=proof['cases'][-1]
+ if category in ['concession','financing','supply','other']:
+ m.transition(m.promoter,id,'submit',status=422);case.update({'editing':'saved/recovered','submission':'blocked-unapproved-module-profile','review':'not-eligible','publication':'blocked'})
+ m.persist();continue
+ p=enrich(p,doc)
+ if category=='investment_project':
+ negative(id,p,'canonical.milestones.0.end_date',lambda q:q['milestones'][0].update({'end_date':'2026-01-01'}))
+ negative(id,p,'canonical.milestones',lambda q:q['milestones'][0].update({'dependencies':[q['milestones'][1]['title']]}))
+ negative(id,p,'canonical.financial_indicators',lambda q:q.update({'maturity_stage':'feasibility'}))
+ p.update({'maturity_stage':'operational','financial_indicators':{'npv':-50,'irr':5,'payback_years':5,'scenario':'Cenário sintético negativo; sem score de sucesso','horizon_years':10,'currency':'MZN','discount_rate':6,'model_document_id':doc}})
+ p['evidences'].append({'title':'Estudo sintético sem validade real','evidence_type':'feasibility_study','document_id':doc})
+ elif category=='real_estate':
+ negative(id,p,'canonical.real_estate.utilities',lambda q:q['real_estate'].update({'utilities':[{'type':'water','status':'existing'}]}))
+ negative(id,p,'canonical.real_estate.title_document_id',lambda q:q['real_estate'].update({'title_document_id':str(uuid.uuid4())}))
+ elif category=='land_rights':
+ negative(id,p,'canonical.land_rights.community_consultation',lambda q:q['land_rights'].update({'communities_affected':True}))
+ else:
+ negative(id,p,'canonical.business_transaction.financial_periods',lambda q:q['business_transaction'].update({'financial_periods':q['business_transaction']['financial_periods'][:1]}))
+ negative(id,p,'canonical.business_transaction.litigation_contingencies',lambda q:q['business_transaction'].update({'litigation_contingencies':[]}))
+ m.save(m.promoter,id,p)
+ recovered=m.page(m.Session('promoter').login(),id)
+ assert recovered['values']['canonical']==m.normalized(p)
+ location=recovered['canonicalOptions']['resources']['locations'][0]['payload']
+ geo=m.promoter.call('GET','/minhas-oportunidades/territory-geometries?territory_id='+location['district_id'])
+ case['territorial_consumer']={'country':location['country_code'],'district_id':location['district_id'],'selected_geometry_available':geo['selected_geometry_available'],'areas_returned':len(geo['areas']),'rendered':False}
+ for s in [m.promoter,m.validator,m.publisher]:
+ raw=s.call('GET',f'/minhas-oportunidades/{id}/resources/documents/{doc}/download',binary=True)
+ assert isinstance(raw,bytes) and raw.startswith(b'\x89PNG')
+ m.sessions['outsider'].call('GET',f'/minhas-oportunidades/{id}/resources/documents/{doc}/download',status=403)
+ m.transition(m.promoter,id,'submit');m.transition(m.validator,id,'assign_review',assignee_user_id=m.actors['validator']['id'])
+ if category=='investment_project':
+ m.transition(m.validator,id,'pending_opinion',gate='technical_review',recipient_user_id=m.actors['bootstrap']['id'])
+ context=m.page(m.validator,id)['profileContext'];opinion=next(iter(context['opinions']))
+ assigned=reviewer.call('GET','/minhas-oportunidades?queue=assigned',inertia=True)['props']['records']['data']
+ assert any(r['id']==id for r in assigned)
+ m.transition(m.validator,id,'approve',status=422)
+ m.transition(m.validator,id,'respond_opinion',status=403,opinion_id=opinion,gate_decision='approved',evidence_document_ids=[doc])
+ m.transition(reviewer,id,'respond_opinion',opinion_id=opinion,gate_decision='approved',evidence_document_ids=[doc])
+ assert 'reviews' not in m.page(m.validator,id)['profileContext']
+ case['opinion']={'recipient_id':m.actors['bootstrap']['id'],'response_saved':True,'approval_while_pending':422,'wrong_recipient':403,'gate_not_automatically_approved':True}
+ m.review(id,doc)
+ if category=='land_rights':
+ m.transition(m.publisher,id,'publish',status=422);case['publication']='blocked-pending-external-authorization'
+ else:
+ m.transition(m.publisher,id,'publish');case['publication']='published-internal'
+ final=m.page(m.Session('promoter').login(),id)
+ case.update({'editing':'saved/recovered','submission':'passed','review':'gates-approved','working_state':final['workflowState'],'document_recovered_allowed_profiles':[21,24,25],'foreign_organization_document_denied':403})
+ m.persist()
+ proof['result']='passed';proof['completed_at']=datetime.now(timezone.utc).isoformat()
+ print(json.dumps({'result':'passed','target':m.EXPECTED,'categories':len(proof['cases']),'negative_fields':len(proof['negative_fields']),'visual_pending':True,'active_writes':0}))
+except Exception:
+ proof['result']='failed';raise
+finally:
+ m.persist()
diff --git a/tools/opportunity-semantic-publication-http-qa.py b/tools/opportunity-semantic-publication-http-qa.py
new file mode 100644
index 00000000..7297cfa3
--- /dev/null
+++ b/tools/opportunity-semantic-publication-http-qa.py
@@ -0,0 +1,116 @@
+"""Scoped editorial assignment and authorized business teaser on the guarded live QA server."""
+import json
+import struct
+import uuid
+import zlib
+from datetime import datetime, timezone
+from portal_profiles_http_session import Session, actors, PRIVATE, BASE, EXPECTED, REASON, events
+
+source = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text())
+assert source['result'] == 'passed' and source['target'] == EXPECTED
+case = next(c for c in source['cases'] if c['category'] == 'business_sale')
+record_id = case['id']
+path = PRIVATE / 'opportunity-semantic-publication-http-qa.json'
+proof = {'target': EXPECTED, 'url': BASE, 'started_at': datetime.now(timezone.utc).isoformat(),
+ 'id': record_id, 'category': 'business_sale', 'active_writes': 0, 'interface_demonstrated': False}
+
+
+def page(s):
+ return s.call('GET', f'/minhas-oportunidades/{record_id}/view', inertia=True)['props']
+
+
+def action(s, name, status=200, **extra):
+ p = page(s)
+ if name == 'publish':
+ extra = {'confirm_publication': True, 'preview_hash': p['profileContext']['approval']['hash'], **extra}
+ return s.call('POST', f'/minhas-oportunidades/{record_id}/workflow',
+ {'etag': p['etag'], 'action': name, 'reason': REASON, **extra}, status=status)
+
+
+def png():
+ def chunk(kind, data):
+ return struct.pack('>I', len(data)) + kind + data + struct.pack('>I', zlib.crc32(kind + data) & 0xffffffff)
+ color = uuid.uuid4().bytes[:3]
+ pixels = b''.join(b'\x00' + color * 512 for _ in range(512))
+ return b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', struct.pack('>IIBBBBB', 512, 512, 8, 2, 0, 0, 0)) + chunk(b'IDAT', zlib.compress(pixels)) + chunk(b'IEND', b'')
+
+
+try:
+ administrator = Session('super_first').login()
+ types = [c['category'] for c in source['cases']]
+ grants = administrator.call('GET', '/perfis/gestao', inertia=True)['props']['assignments']
+ for key, responsibilities in [('publisher', ['publication_coordinator']), ('bootstrap', [])]:
+ if not any(g['user_id'] == actors[key]['id'] and g['role'] == 'publisher' and g['revoked_at'] is None
+ and set(responsibilities).issubset(json.loads(g['responsibilities']))
+ and set(types).issubset(json.loads(g['opportunity_types'])) for g in grants):
+ administrator.call('POST', '/perfis/atribuicoes', {'user_id': actors[key]['id'], 'role': 'publisher',
+ 'opportunity_types': types, 'responsibilities': responsibilities,
+ 'reason': 'Atribuição editorial estritamente sintética QA; sem responsáveis institucionais reais'}, status=201)
+ promoter = Session('promoter').login()
+ reviewer = Session('validator').login()
+ coordinator = Session('publisher').login()
+ assigned = Session('bootstrap').login()
+ if page(promoter)['workflowState'] == 'published':
+ action(promoter, 'request_revision')
+ else:
+ assert page(promoter)['workflowState'] == 'needs_information'
+ p = page(promoter)['values']['canonical']
+ p['visibility'] = 'public'
+ p['executive_summary'] += ' MARCADOR-RESUMO-PRIVADO-SEMANTICA-QA.'
+ p['demand_statement'] += ' MARCADOR-DADOS-PRIVADOS-SEMANTICA-QA.'
+ teaser = 'Resumo sintético QA autorizado para publicação; sem informação privada nem validade comercial.'
+ p['business_transaction']['teaser'] = teaser
+ existing_resources = promoter.call('GET', f'/minhas-oportunidades/{record_id}/resources', inertia=True)['props']['resources']
+ existing = next((i for i in existing_resources['images'] if i['payload'].get('caption') == 'Ilustração sintética QA' and not i.get('deleted_at')), None)
+ image = {'id': existing['id']} if existing else promoter.call('POST', f'/minhas-oportunidades/{record_id}/resources/images', {
+ 'etag': page(promoter)['etag'], 'creation_key': str(uuid.uuid4()), 'reason': REASON,
+ 'payload': json.dumps({'title': 'Imagem sintética QA', 'caption': 'Ilustração sintética QA',
+ 'alt_text': 'Imagem sintética colorida', 'is_cover': True, 'rights_status': 'owned', 'visibility': 'public'})
+ }, multipart=png(), status=201)
+ resources = promoter.call('GET', f'/minhas-oportunidades/{record_id}/resources', inertia=True)['props']['resources']
+ row = next(i for i in resources['images'] if i['id'] == image['id'])
+ proof['image_id'] = image['id']
+ assert row['file']['malware_scan_status'] == 'clean'
+ if not row['payload'].get('derivatives'):
+ promoter.call('POST', f"/minhas-oportunidades/{record_id}/resources/images/{image['id']}/prepare",
+ {'etag': page(promoter)['etag'], 'version': row['version'], 'reason': REASON})
+ resources = promoter.call('GET', f'/minhas-oportunidades/{record_id}/resources', inertia=True)['props']['resources']
+ row = next(i for i in resources['images'] if i['id'] == image['id'])
+ assert len(row['derivativePreviews']) >= 2
+ for derivative in row['derivativePreviews']:
+ assert promoter.call('GET', derivative['url'].replace(BASE, ''), binary=True)
+ p['images'] = [image['id']]
+ promoter.call('PUT', f'/minhas-oportunidades/{record_id}/draft', {'etag': page(promoter)['etag'], 'canonical': p, 'reason': REASON})
+ action(promoter, 'submit')
+ action(reviewer, 'assign_review', assignee_user_id=actors['validator']['id'])
+ for gate in page(reviewer)['canonicalOptions']['gates']:
+ action(reviewer, 'review_gate', gate=gate, gate_decision='approved', evidence_document_ids=[case['document_id']])
+ action(reviewer, 'approve')
+ action(coordinator, 'assign_publication', assignee_user_id=actors['bootstrap']['id'])
+ queue = assigned.call('GET', '/minhas-oportunidades?queue=assigned', inertia=True)['props']
+ assert any(r['id'] == record_id for r in queue['records']['data'])
+ action(coordinator, 'publish', status=403)
+ preview = page(assigned)['publicationPreview']
+ assert preview['summary'] == preview['description'] == teaser
+ action(assigned, 'publish')
+ recovered = page(Session('promoter').login())
+ assert recovered['workflowState'] == 'published'
+ assert recovered['values']['canonical']['executive_summary'] == p['executive_summary']
+ anonymous = Session('outsider')
+ public_url = '/api/v1/opportunities/' + recovered['record']['slug']
+ output = anonymous.call('GET', public_url)
+ serialized = json.dumps(output, ensure_ascii=False)
+ assert teaser in serialized and 'MARCADOR-RESUMO-PRIVADO' not in serialized and 'MARCADOR-DADOS-PRIVADOS' not in serialized
+ proof.update({'result': 'passed', 'coordinator_id': actors['publisher']['id'], 'assignee_id': actors['bootstrap']['id'],
+ 'assigned_queue_persisted': True, 'different_publisher_denied': 403, 'published': 'public',
+ 'public_route': public_url, 'public_teaser_only': True, 'private_content_preserved': True,
+ 'recovered_in_new_mfa_session': True, 'original_clamd_clean': True, 'derived_previews_recovered': len(row['derivativePreviews']),
+ 'publication_task_id': recovered['profileContext']['publication_task_id']})
+except Exception as error:
+ proof.update({'result': 'failed', 'failure': str(error)})
+ raise
+finally:
+ proof['events'] = events
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ path.write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({k: proof[k] for k in ['result', 'target', 'id', 'public_teaser_only', 'active_writes']}))
diff --git a/tools/opportunity-semantic-verify-qa.php b/tools/opportunity-semantic-verify-qa.php
new file mode 100644
index 00000000..dc46cda9
--- /dev/null
+++ b/tools/opportunity-semantic-verify-qa.php
@@ -0,0 +1,52 @@
+make(Kernel::class)->bootstrap();
+$identity = portalQaAssertTarget($target);
+config(['portal.profile_access_enabled' => true, 'portal.opportunity_specialized_drafts_enabled' => true]);
+$directory = dirname(__DIR__).'/storage/app/private/investmoz-v2/portal-audit';
+$http = json_decode(file_get_contents($directory.'/opportunity-semantic-http-qa.json'), true, 512, JSON_THROW_ON_ERROR);
+throw_unless($http['result'] === 'passed' && $http['target'] === $identity->database.':'.$identity->port, RuntimeException::class, 'QA proof mismatch');
+DB::beginTransaction();
+DB::statement('SET TRANSACTION READ ONLY');
+$result = ['target' => $identity, 'captured_at' => gmdate('c'), 'active_writes' => 0, 'visual_pending' => true,
+ 'contract_version' => OpportunityCanonicalContract::VERSION, 'categories' => []];
+foreach ($http['cases'] as $case) {
+ $record = Opportunity::findOrFail($case['id']);
+ $row = ['id' => $record->id, 'category' => $case['category'], 'working_state' => app(PortalProfileAccess::class)->state($record), 'publication_status' => $record->status];
+ try {
+ $snapshot = app(OpportunityCanonicalContract::class)->validateSubmission($record);
+ $row += ['canonical_validation' => 'passed', 'payload_sha256' => $snapshot['hash'], 'resources' => array_map('count', $snapshot['resources']),
+ 'countries' => array_map(fn ($r) => $r['payload']['country_code'], $snapshot['resources']['locations'])];
+ } catch (ValidationException $error) {
+ $row += ['canonical_validation' => 'blocked', 'missing' => array_keys($error->errors())];
+ }
+ $result['categories'][] = $row;
+}
+$counts = array_count_values(array_column($result['categories'], 'canonical_validation'));
+throw_unless($counts === ['passed' => 6, 'blocked' => 4], RuntimeException::class, 'Unexpected current semantic coverage');
+$docIds = DB::table('opportunity_documents')->whereIn('opportunity_id', array_column($http['cases'], 'id'))->pluck('document_id')->all();
+$imageIds = DB::table('opportunity_images')->whereIn('opportunity_id', array_column($http['cases'], 'id'))->pluck('document_id')->all();
+$result['document_scans'] = DB::table('documents')->whereIn('id', [...$docIds, ...$imageIds])->get(['id', 'media_type', 'sha256', 'malware_scanned_sha256', 'malware_scan_status', 'malware_engine', 'storage_encryption']);
+$result['territories'] = ['registered' => DB::table('geo_locations')->whereNull('deleted_at')->count(), 'geometries' => DB::table('geo_geometries')->whereNull('deleted_at')->count(), 'visual' => 'pending'];
+$keys = Opportunity::whereIn('id', array_column($http['cases'], 'id'))->pluck('management_creation_key')->all();
+$result['tasks'] = DB::table('tasks')->where('source_system', 'opportunity-workflow')->whereIn('correlation_id', $keys)->get(['id', 'external_id', 'task_type', 'status', 'assignee_user_id', 'due_at']);
+$promoter = User::findOrFail(21);
+$result['promoter'] = ['id' => $promoter->id, 'name' => $promoter->name, 'mfa_confirmed' => $promoter->two_factor_confirmed_at !== null, 'contexts' => app(PortalProfileAccess::class)->navigation($promoter)['contexts']];
+$result['active_manifest_sha256'] = hash_file('sha256', dirname(__DIR__).'/public/build/manifest.json');
+$result['qa_manifest_sha256'] = hash_file('sha256', dirname(__DIR__).'/public/build-qa-opportunities/manifest.json');
+$result['source_schema_sha256'] = hash_file('sha256', resource_path('data/investmoz-opportunity-modular.schema.json'));
+DB::rollBack();
+file_put_contents($directory.'/opportunity-semantic-verification-qa.json', json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode(['target' => $identity, 'categories' => $counts, 'active_writes' => 0, 'visual_pending' => true]).PHP_EOL;
diff --git a/tools/opportunity-workflow-extended-http-qa.py b/tools/opportunity-workflow-extended-http-qa.py
new file mode 100644
index 00000000..23559c3c
--- /dev/null
+++ b/tools/opportunity-workflow-extended-http-qa.py
@@ -0,0 +1,70 @@
+"""Additional live QA evidence: independent appeal, public editorial gates and external dependencies."""
+import importlib.util
+from pathlib import Path
+spec=importlib.util.spec_from_file_location('opportunity_workflow_http_qa',Path(__file__).with_name('opportunity-workflow-http-qa.py'))
+module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module)
+globals().update({name:getattr(module,name) for name in ['Session','actors','PRIVATE','EXPECTED','REASON','events','page','transition','save','png','review','superuser','promoter','validator','publisher']})
+import json
+import uuid
+from datetime import datetime, timezone
+
+previous = json.loads((PRIVATE / 'opportunity-workflow-http-qa.json').read_text())
+assert previous['result']=='passed' and previous['target']==EXPECTED
+case = next(c for c in previous['cases'] if c['category']=='real_estate')
+land = next(c for c in previous['cases'] if c['category']=='land_rights')
+id=case['id'];document=case['document_id']
+proof={'target':EXPECTED,'active_writes':0,'interface_demonstrated':False,'started_at':datetime.now(timezone.utc).isoformat()}
+path=PRIVATE/'opportunity-workflow-extended-http-qa.json'
+
+try:
+ assignments=superuser.call('GET','/perfis/gestao',inertia=True)['props']['assignments']
+ existing=[g for g in assignments if g['user_id']==actors['bootstrap']['id'] and g['role']=='validator' and g['revoked_at'] is None and 'appeal_reviewer' in json.loads(g['responsibilities'])]
+ if not existing:
+ superuser.call('POST','/perfis/atribuicoes',{'user_id':actors['bootstrap']['id'],'role':'validator','opportunity_types':['real_estate'],
+ 'responsibilities':['appeal_reviewer'],'reason':'Instância independente estritamente sintética QA, sem designar responsável real'},status=201)
+ appeal=Session('bootstrap').login()
+ transition(appeal,id,'appeal_reopen')
+ recovered=Session('promoter').login().call('GET',f'/minhas-oportunidades/{id}/view',inertia=True)['props']
+ assert recovered['workflowState']=='needs_information' and not recovered['profileContext']['appeal']['pending']
+ proof['appeal']={'id':id,'rejector_id':actors['validator']['id'],'appeal_reviewer_id':actors['bootstrap']['id'],'independent_decision':'reopen','recovered_in_new_session':True}
+ # No extra copies of originals: new image is a separate, deliberately distinct synthetic fixture.
+ image=promoter.call('POST',f'/minhas-oportunidades/{id}/resources/images',{'etag':page(promoter,id)['etag'],'creation_key':str(uuid.uuid4()),'reason':REASON,
+ 'payload':json.dumps({'title':'Imagem sintética QA','caption':'Ilustração sintética para ensaio QA','alt_text':'Área colorida gerada exclusivamente para QA','is_cover':True,'rights_status':'owned','visibility':'public'})},multipart=png(id+100),status=201)
+ resources=promoter.call('GET',f'/minhas-oportunidades/{id}/resources',inertia=True)['props']['resources']
+ row=next(i for i in resources['images'] if i['id']==image['id'])
+ assert row['file']['malware_scan_status']=='clean'
+ promoter.call('POST',f"/minhas-oportunidades/{id}/resources/images/{image['id']}/prepare",{'etag':page(promoter,id)['etag'],'version':row['version'],'reason':REASON})
+ resources=promoter.call('GET',f'/minhas-oportunidades/{id}/resources',inertia=True)['props']['resources']
+ row=next(i for i in resources['images'] if i['id']==image['id'])
+ assert row['payload']['derivatives'] and len(row['derivativePreviews'])==len(row['payload']['derivatives'])
+ p=page(promoter,id)['values']['canonical'];p.update({'visibility':'public','images':[image['id']],'review_due_date':'2027-01-01'})
+ p['real_estate']['price']=None
+ save(promoter,id,p);transition(promoter,id,'submit',status=422)
+ p['real_estate']['price']=1000
+ save(promoter,id,p);transition(promoter,id,'submit');transition(validator,id,'start_review');review(id,document)
+ transition(publisher,id,'publish',status=422,confirm_publication=False)
+ transition(publisher,id,'publish',status=409,preview_hash='0'*64)
+ transition(publisher,id,'publish')
+ published=page(promoter,id)
+ public=Session('public').login()
+ response=public.call('GET','/api/v1/opportunities/'+published['record']['slug'])
+ serialized=json.dumps(response)
+ assert 'canonical' not in serialized and 'workflow_context' not in serialized and 'internal_contact_id' not in serialized
+ proof['public_publication']={'id':id,'public_route':'/api/v1/opportunities/'+published['record']['slug'],'image_original_clean':True,'derived_previews':len(row['derivativePreviews']),
+ 'preview_confirmation_enforced':True,'preview_hash_enforced':True,'private_fields_not_exposed':True}
+ transition(promoter,id,'request_revision');p['official_title']+=' — proposta privada não publicada';save(promoter,id,p)
+ still_public=public.call('GET','/api/v1/opportunities/'+published['record']['slug'])
+ assert 'proposta privada não publicada' not in json.dumps(still_public)
+ transition(publisher,id,'suspend')
+ public.call('GET','/api/v1/opportunities/'+published['record']['slug'],status=404)
+ proof['material_change_and_suspend']={'id':id,'public_version_preserved_while_preparing':True,'approval_invalidated':True,'suspended_public_get':404}
+ # All internal gates may be recorded, but do not manufacture the missing external authorization.
+ transition(validator,land['id'],'start_review');review(land['id'],land['document_id'])
+ transition(publisher,land['id'],'publish',status=422)
+ proof['external_authorization']={'id':land['id'],'internal_approval':'approved','external_authorization':'pending','publication_status':422,'external_decision_not_fabricated':True}
+ proof['result']='passed';proof['completed_at']=datetime.now(timezone.utc).isoformat()
+ print(json.dumps({'result':'passed','target':EXPECTED,'appeal_id':id,'independent_actor':actors['bootstrap']['id'],'real_image_derivatives':len(row['derivativePreviews']),'visual_pending':True,'active_writes':0}))
+except Exception:
+ proof['result']='failed';raise
+finally:
+ proof['events']=events;path.write_text(json.dumps(proof,indent=2),encoding='utf-8')
diff --git a/tools/opportunity-workflow-fixtures-qa.php b/tools/opportunity-workflow-fixtures-qa.php
new file mode 100644
index 00000000..db706140
--- /dev/null
+++ b/tools/opportunity-workflow-fixtures-qa.php
@@ -0,0 +1,50 @@
+make(Kernel::class)->bootstrap();
+$identity = portalQaAssertTarget($target);
+$directory = $root.'/storage/app/private/investmoz-v2/portal-audit';
+$path = $directory.'/opportunity-workflow-fixtures-qa.json';
+if (is_file($path)) {
+ $receipt = json_decode(file_get_contents($path), true, 512, JSON_THROW_ON_ERROR);
+ throw_unless($receipt['target']['database'] === $identity->database && DB::table('economic_activities')->where('id', $receipt['activity_id'])->exists(), RuntimeException::class, 'Existing fixture target/reference mismatch');
+ echo json_encode(['target' => $identity, 'synthetic_fixture_reused' => true, 'active_writes' => 0]).PHP_EOL;
+ exit;
+}
+$orgs = json_decode(file_get_contents($directory.'/profiles-v1-organizations-qa.json'), true, 512, JSON_THROW_ON_ERROR);
+$receipt = DB::transaction(function () use ($identity, $orgs) {
+ $version = (string) Str::uuid();
+ DB::table('reference_catalog_versions')->insert(['id' => $version, 'catalog_code' => 'qa-opportunity-synthetic', 'version_no' => 1,
+ 'source_system' => 'qa-synthetic-fixture', 'source_version' => 'qa-20261010', 'source_reference' => 'Synthetic test data only, not an official economic classification',
+ 'status' => 'published', 'created_at' => now(), 'updated_at' => now()]);
+ $previous = null;
+ $ids = [];
+ foreach (['Sector sintético QA', 'Subsector sintético QA', 'Atividade sintética QA'] as $i => $name) {
+ $sector = DB::table('sectors')->insertGetId(['name' => $name, 'slug' => 'qa-workflow-level-'.$i, 'is_active' => true, 'created_at' => now(), 'updated_at' => now()]);
+ $id = (string) Str::uuid();
+ DB::table('economic_activities')->insert(['id' => $id, 'catalog_version_id' => $version, 'parent_id' => $previous,
+ 'sector_id' => $sector, 'code' => 'qa-level-'.$i, 'label_pt_mz' => $name, 'status' => 'published', 'valid_from' => '2026-10-10', 'created_at' => now(), 'updated_at' => now()]);
+ $ids[] = ['id' => $id, 'sector_id' => $sector];
+ $previous = $id;
+ }
+ $investor = (string) Str::uuid();
+ $contact = (string) Str::uuid();
+ DB::table('investors')->insert(['id' => $investor, 'source_system' => 'qa-synthetic-fixture', 'organization_id' => $orgs['organization'],
+ 'legal_name' => 'Entidade sintética QA — sem validade real', 'investor_type' => 'institutional', 'status' => 'active']);
+ DB::table('contacts')->insert(['id' => $contact, 'source_system' => 'qa-synthetic-fixture', 'full_name' => 'Contacto sintético QA — oportunidade', 'email' => 'workflow-contact@example.invalid']);
+ DB::table('investor_contacts')->insert(['investor_id' => $investor, 'contact_id' => $contact, 'is_primary' => true]);
+
+ return ['target' => $identity, 'synthetic_only' => true, 'sector_id' => $ids[0]['sector_id'], 'subsector_id' => $ids[1]['id'], 'activity_id' => $ids[2]['id'],
+ 'contact_id' => $contact, 'organization_id' => $orgs['organization'], 'catalog_version_id' => $version, 'active_writes' => 0];
+});
+file_put_contents($path, json_encode($receipt, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode(['target' => $identity, 'synthetic_only' => true, 'canonical_reference_fixture_prepared' => true, 'active_writes' => 0]).PHP_EOL;
diff --git a/tools/opportunity-workflow-http-qa.py b/tools/opportunity-workflow-http-qa.py
new file mode 100644
index 00000000..43fdacef
--- /dev/null
+++ b/tools/opportunity-workflow-http-qa.py
@@ -0,0 +1,179 @@
+"""Canonical contracts/workflow through QA HTTP with real Fortify MFA and ClamD. Sanitized output."""
+from portal_profiles_http_session import Session, actors, PRIVATE, BASE, EXPECTED, REASON, events
+import json
+import uuid
+import hashlib
+import zlib
+import struct
+from datetime import datetime, timezone
+
+fixtures = json.loads((PRIVATE / 'opportunity-workflow-fixtures-qa.json').read_text())
+old = json.loads((PRIVATE / 'profiles-v1-http-receipts-qa.json').read_text())
+path = PRIVATE / 'opportunity-workflow-http-qa.json'
+proof = {'target': EXPECTED, 'url': BASE, 'started_at': datetime.now(timezone.utc).isoformat(), 'interface_demonstrated': False, 'active_writes': 0, 'cases': []}
+sessions = {role: Session(role).login() for role in ['promoter', 'colleague', 'validator', 'publisher', 'outsider', 'multiple', 'super_first']}
+promoter = sessions['promoter']; validator = sessions['validator']; publisher = sessions['publisher']; superuser = sessions['super_first']
+types = ['investment_project', 'real_estate', 'land_rights', 'business_sale', 'business_partnership', 'franchise', 'concession', 'financing', 'supply', 'other']
+
+
+def persist():
+ proof['events'] = events
+ path.write_text(json.dumps(proof, indent=2), encoding='utf-8')
+
+
+def prepare_roles():
+ assignments=superuser.call('GET','/perfis/gestao',inertia=True)['props']['assignments']
+ def available(role,access,responsibilities=()):
+ return any(g['user_id']==actors[role]['id'] and g['role']==access and g['revoked_at'] is None
+ and set(types).issubset(json.loads(g['opportunity_types'])) and set(responsibilities).issubset(json.loads(g['responsibilities'])) for g in assignments)
+ if available('promoter','promoter') and available('validator','validator',['validation_coordinator','technical_reviewer','legal_reviewer']) and available('publisher','publisher') and available('multiple','publisher') and available('colleague','validator',['appeal_reviewer']):
+ return
+ # Additional scope uses the normal request and independent approval, preserving earlier grants.
+ request = promoter.call('POST', '/perfil/promotor', {'creation_key': str(uuid.uuid4()), 'representation_type': 'company',
+ 'organization_id': fixtures['organization_id'], 'opportunity_types': types, 'document_ids': [old['requests']['promoter']['document_id']], 'reason': REASON}, status=201)
+ superuser.call('POST', f"/perfis/pedidos/{request['id']}/decisao", {'version': 1, 'decision': 'approved', 'approved_types': types,
+ 'verified_identity': True, 'verified_representation': True, 'verified_documents': True, 'reason': 'Aprovação de dados estritamente sintéticos QA; não verifica identidade real'})
+ for role, access, responsibilities in [('validator','validator',['validation_coordinator','technical_reviewer','legal_reviewer']), ('publisher','publisher',[]), ('multiple','publisher',[]), ('colleague','validator',['appeal_reviewer'])]:
+ superuser.call('POST', '/perfis/atribuicoes', {'user_id': actors[role]['id'], 'role': access, 'opportunity_types': types, 'responsibilities': responsibilities, 'reason': REASON}, status=201)
+
+
+def page(s, id):
+ return s.call('GET', f'/minhas-oportunidades/{id}/view', inertia=True)['props']
+
+
+def transition(s, id, action, status=200, **data):
+ p = page(s, id)
+ if action=='publish':
+ data={'confirm_publication':True,'preview_hash':p['profileContext'].get('approval',{}).get('hash','0'*64),**data}
+ return s.call('POST', f'/minhas-oportunidades/{id}/workflow', {'etag': p['etag'], 'action': action, 'reason': REASON, **data}, status=status)
+
+
+def save(s, id, canonical, status=200):
+ p = page(s, id)
+ return s.call('PUT', f'/minhas-oportunidades/{id}/draft', {'etag': p['etag'], 'canonical': canonical, 'reason': REASON}, status=status)
+
+
+def normalized(value):
+ if isinstance(value,str): return value.strip()
+ if isinstance(value,list): return [normalized(v) for v in value]
+ if isinstance(value,dict): return {k:normalized(v) for k,v in value.items()}
+ return value
+
+
+def png(seed):
+ def chunk(t, raw):
+ return struct.pack('>I', len(raw)) + t + raw + struct.pack('>I', zlib.crc32(t + raw) & 0xffffffff)
+ pixels = b''.join(b'\x00' + bytes([20 + seed % 200, 90, 140]) * 512 for _ in range(512))
+ return b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', struct.pack('>IIBBBBB', 512, 512, 8, 2, 0, 0, 0)) + chunk(b'IDAT', zlib.compress(pixels)) + chunk(b'IEND', b'')
+
+
+def create(category):
+ draft = promoter.call('POST', '/minhas-oportunidades/drafts', {'creation_key': str(uuid.uuid4()), 'organization_id': fixtures['organization_id'],
+ 'opportunity_category': category, 'title': 'Oportunidade sintética QA ' + category, 'canonical': {'opportunity_category': category}, 'reason': REASON}, status=201)
+ id = draft['id']; transition(promoter, id, 'submit', status=422)
+ first = page(promoter, id)
+ assert first['canonicalOptions']['version'] == 'opportunity-canonical-adapter-20261010-semantic1'
+ provinces = promoter.call('GET', '/minhas-oportunidades/territory-options?type=province')['data']
+ province = provinces[0]
+ districts = promoter.call('GET', '/minhas-oportunidades/territory-options?type=district&parent_id=' + province['id'])['data']
+ district = districts[0]
+ location = promoter.call('POST', f'/minhas-oportunidades/{id}/resources/locations', {'etag': page(promoter,id)['etag'], 'creation_key': str(uuid.uuid4()), 'reason': REASON,
+ 'payload': {'country_code':'MZ','province_id':province['id'],'district_id':district['id'],'role':'headquarters','is_primary':True}}, status=201)
+ raw = png(id)
+ document = promoter.call('POST', f'/minhas-oportunidades/{id}/resources/documents', {'etag':page(promoter,id)['etag'], 'creation_key':str(uuid.uuid4()), 'reason':REASON,
+ 'payload':json.dumps({'title':'Documento de ensaio sintético — sem validade real','category':'qa-synthetic','classification':'restricted','visibility':'internal'})}, multipart=raw, status=201)
+ resources = promoter.call('GET',f'/minhas-oportunidades/{id}/resources',inertia=True)['props']['resources']
+ doc = next(d for d in resources['documents'] if d['id']==document['id'])
+ assert doc['file']['malware_scan_status']=='clean' and doc['file']['sha256'].strip()==hashlib.sha256(raw).hexdigest()
+ payload = {'opportunity_category':category,'official_title':'Oportunidade sintética QA '+category, 'promoter_id':fixtures['organization_id'], 'promoter_type':'private',
+ 'internal_contact_id':fixtures['contact_id'], 'sector_id':fixtures['sector_id'], 'subsector_id':fixtures['subsector_id'], 'economic_activity_id':fixtures['activity_id'],
+ 'location_mode':'single','geographic_scope':'district','locations':[location['id']], 'executive_summary':('Cenário sintético exclusivamente QA, sem oferta ou decisão real. ' * 7).strip(),
+ 'demand_statement':('Necessidade fictícia para verificar recuperação e decisões independentes. '*3).strip(),'documents':[document['id']],
+ 'evidences':[{'title':'Comprovativo sintético','evidence_type':'qa-synthetic','document_id':document['id']}],
+ 'publication_languages':[{'language_code':'pt-MZ','title':'Oportunidade sintética QA','summary':'Texto de demonstração QA'}], 'visibility':'internal','truth_declaration':True}
+ details = {'investment_project': {'opportunity_type':'greenfield','maturity_stage':'idea','investment_modalities':['equity'],'investor_profiles':['institutional'],
+ 'products':[{'name':'Produto QA','category':'qa'}], 'assets':[{'name':'Ativo QA','asset_type':'qa'}], 'markets':[{'name':'Mercado QA','market_type':'domestic','country_code':'MZ'}],
+ 'competitive_advantage':'Diferenciação fictícia exclusivamente para ensaio QA. '*4,'employment':{'employment_type':'permanent','direct_jobs':2},
+ 'impact_indicators':[{'impact_type':'qa','description':'Impacto fictício QA'}],'total_investment':1000,'currency':'MZN',
+ 'investment_breakdown':[{'label':'Rubrica QA','amount':1000,'currency':'MZN'}], 'secured_financing':[], 'funding_sought':1000,
+ 'milestones':[{'title':'Preparação QA','due_date':'2027-01-01','status':'planned'},{'title':'Execução QA','due_date':'2027-02-01','status':'planned'}],
+ 'licenses':[{'name':'Declaração QA de aplicabilidade','authority':'Entidade fictícia QA','status':'not_applicable'}],
+ 'environmental_social':{'assessment_status':'qa','environmental_category':'qa'},'risks':[{'title':'Risco sintético QA','category':'qa','likelihood':1,'severity':1,'mitigation':'Medida de ensaio QA'}]},
+ 'real_estate':{'real_estate':{'transaction_type':'sale','property_type':'warehouse','construction_status':'completed','property_condition':'good','land_area':1000,'built_area':500,'area_unit':'sqm',
+ 'utilities':[{'type':'water','status':'existing'}], 'occupancy_status':'vacant','title_type':'qa-synthetic','registration_number':'QA-'+str(id),'encumbrances':[{'type':'none'}],
+ 'valuation':{'value':1000,'date':'2026-10-10','method':'qa-only','appraiser':'Synthetic QA','document_id':document['id']},'price':1000,'use_license_document_id':document['id']}},
+ 'land_rights':{'land_rights':{'operation_type':'investment_with_duat','duat_status':'application','holder_name':'Titular sintético QA','authorized_purpose':'Preparação sintética QA',
+ 'parcels':[{'location_id':location['id'],'area':1000,'geometry':{'type':'MultiPolygon','coordinates':[[[[40,-13],[40.001,-13],[40.001,-12.999],[40,-12.999],[40,-13]]]]},'overlap_status':'qa-pending'}],
+ 'overlaps_conflicts':[{'type':'none','status':'qa-only'}],'required_authorizations':[{'name':'Decisão externa ainda necessária','status':'pending'}]}},
+ }
+ if category in ['business_sale','business_partnership','franchise']:
+ transaction = {'business_sale':'full_sale','business_partnership':'partnership','franchise':'franchise'}[category]
+ details[category] = {'business_transaction':{'transaction_type':transaction,'legal_entity_id':fixtures['organization_id'],'legal_form':'Synthetic QA','asking_price':1000,
+ 'valuation':{'value':1000,'date':'2026-10-10','method':'QA'},'financial_periods':[{'year':2025,'document_id':document['id']}], 'assets_liabilities':{'assets':'QA','liabilities':'QA'},
+ 'employees':{'total':2}, 'contracts_licenses':[{'name':'QA','document_id':document['id']}],'litigation_contingencies':[], 'reason_for_transaction':'Operação fictícia para validar contratos, versões e permissões em QA. ',
+ 'confidentiality_level':'restricted','due_diligence_status':'data_room_ready', **({'percentage_offered':100 if category=='business_sale' else 40,'governance_rights':{'voting':'QA'}} if category!='franchise' else {'franchise_terms':{'brand':'QA','territory':'QA','term':'QA'}}),
+ **({'partner_contribution':{'capital':1000,'calendar':'QA'}} if category=='business_partnership' else {})}}
+ payload.update(details.get(category,{'module_profile_version':'qa-unapproved'}))
+ payload=normalized(payload)
+ save(promoter,id,payload)
+ new = Session('promoter').login(); recovered = page(new,id)
+ assert recovered['values']['canonical']==payload and recovered['canonicalOptions']['resources']['locations'][0]['payload']['country_code']=='MZ'
+ proof['cases'].append({'category':category,'id':id,'draft_saved_incomplete':True,'recovered_in_new_mfa_session':True,'document_id':document['id'],'location_id':location['id'],'clamd_real_clean':True})
+ persist()
+ return id, payload, document['id']
+
+
+def review(id, document):
+ gates = page(validator,id)['canonicalOptions']['gates']
+ for gate in gates:
+ transition(validator,id,'review_gate',gate=gate,gate_decision='approved',evidence_document_ids=[document])
+ transition(validator,id,'approve')
+
+
+if __name__ == '__main__':
+ try:
+ prepare_roles()
+ # MFA session revisions may have changed when the new scope was granted.
+ sessions.update({r:Session(r).login() for r in ['promoter','validator','publisher','colleague','multiple']})
+ promoter=sessions['promoter'];validator=sessions['validator'];publisher=sessions['publisher']
+ nav=promoter.call('GET','/dashboard',inertia=True)['props']['profileAccess']
+ promoter.call('GET',nav['mine'],inertia=True);promoter.call('GET',nav['create'],inertia=True)
+ id,payload,doc=create('investment_project')
+ transition(promoter,id,'submit')
+ transition(validator,id,'assign_review',assignee_user_id=actors['validator']['id'])
+ transition(validator,id,'approve',status=422)
+ transition(validator,id,'request_correction',correction_items=['canonical.demand_statement'])
+ payload['demand_statement']+=' Informação sintética corrigida pelo Promotor QA.'
+ save(promoter,id,payload);transition(promoter,id,'submit');transition(validator,id,'start_review');review(id,doc)
+ transition(sessions['multiple'],id,'approve',status=403)
+ transition(publisher,id,'publish')
+ published=page(promoter,id)
+ assert published['workflowState']=='published' and published['profileContext']['publication']['visibility']=='internal'
+ transition(promoter,id,'request_revision');payload['official_title']+=' — alteração material';save(promoter,id,payload)
+ revised=page(promoter,id)
+ assert revised['record']['title']==published['record']['title'] and 'approval' not in revised['profileContext'] and revised['workflowState']=='needs_information'
+ transition(publisher,id,'publish',status=409);transition(publisher,id,'suspend')
+ assert page(promoter,id)['record']['status']=='suspended'
+ proof['positive_cycle']={'id':id,'promoter':actors['promoter']['id'],'validator':actors['validator']['id'],'publisher':actors['publisher']['id'],
+ 'path':['create','save','new_session','recover','submit','assign_review','request_correction','correct','resubmit','review_gates','approve','publish','request_revision','material_edit','suspend'],
+ 'publication_visibility':'internal','published_columns_preserved_during_revision':True,'approval_invalidated':True,'sla_unconfigured':True}
+ for category in ['real_estate','land_rights','business_sale','business_partnership','franchise','concession','financing','supply','other']:
+ other,p,document=create(category)
+ if category in ['concession','financing','supply','other']:
+ transition(promoter,other,'submit',status=422)
+ proof['cases'][-1]['submission']='blocked-unapproved-module-profile'
+ else:
+ transition(promoter,other,'submit');proof['cases'][-1]['submission']='passed'
+ if category=='real_estate':
+ transition(validator,other,'reject',status=422,reason='curto')
+ transition(validator,other,'reject');transition(promoter,other,'appeal')
+ transition(validator,other,'appeal_reopen',status=403)
+ # Same-organization colleague with another role is still conflicted, not an appeal instance.
+ transition(sessions['colleague'],other,'appeal_reopen',status=403)
+ proof['reasoned_rejection_and_appeal']={'id':other,'reason_persisted':True,'same_rejector_denied':True,'organization_conflict_denied':True,'independent_appeal_decision':'pending-authorized-independent-actor'}
+ sessions['outsider'].call('GET',f'/minhas-oportunidades/{other}/view',status=403,inertia=True)
+ persist()
+ proof['completed_at']=datetime.now(timezone.utc).isoformat();proof['result']='passed';persist()
+ print(json.dumps({'result':'passed','target':EXPECTED,'categories':len(proof['cases']),'positive_cycle_id':id,'promoter_qa_id':actors['promoter']['id'],'visual_pending':True,'active_writes':0}))
+ except Exception:
+ proof['result']='failed';persist();raise
diff --git a/tools/opportunity-workflow-multirole-http-qa.py b/tools/opportunity-workflow-multirole-http-qa.py
new file mode 100644
index 00000000..74ff30ea
--- /dev/null
+++ b/tools/opportunity-workflow-multirole-http-qa.py
@@ -0,0 +1,31 @@
+"""Temporary synthetic QA role accumulation; revoke temporary grants and retain all history."""
+import importlib.util
+from pathlib import Path
+import json
+from datetime import datetime, timezone
+
+spec=importlib.util.spec_from_file_location('workflow_support',Path(__file__).with_name('opportunity-workflow-http-qa.py'))
+m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m)
+proof={'target':m.EXPECTED,'active_writes':0,'visual_pending':True,'started_at':datetime.now(timezone.utc).isoformat()}
+previous=json.loads((m.PRIVATE/'opportunity-workflow-http-qa.json').read_text())
+land=next(c for c in previous['cases'] if c['category']=='land_rights')
+grants=[]
+try:
+ for actor,role,types in [('promoter','validator',['land_rights']),('promoter','publisher',['land_rights']),('validator','publisher',['land_rights'])]:
+ g=m.superuser.call('POST','/perfis/atribuicoes',{'user_id':m.actors[actor]['id'],'role':role,'opportunity_types':types,
+ 'responsibilities':[],'reason':'Acumulação temporária de papéis em conta sintética QA para verificar negações'},status=201)
+ grants.append(g['id'])
+ author=m.Session('promoter').login();approver=m.Session('validator').login()
+ m.transition(author,land['id'],'approve',status=403)
+ m.transition(author,land['id'],'publish',status=403)
+ m.transition(approver,land['id'],'publish',status=403)
+ m.transition(m.sessions['multiple'],land['id'],'approve',status=403)
+ proof['denials']={'author_with_promoter_validator_publisher':403,'approver_with_validator_publisher':403,'organization_contributor_with_auditor':403}
+ proof['result']='passed'
+finally:
+ for id in grants:
+ m.superuser.call('POST','/perfis/atribuicoes/'+id+'/revogar',{'reason':'Conclusão do ensaio sintético de acumulação; histórico da atribuição preservado'})
+ fresh=m.Session('promoter').login();fresh.call('GET','/dashboard',inertia=True)
+ proof['temporary_grants_revoked']=len(grants);proof['promoter_new_mfa_session_after_revocation']=True;proof['events']=m.events;proof['completed_at']=datetime.now(timezone.utc).isoformat()
+ (m.PRIVATE/'opportunity-workflow-multirole-http-qa.json').write_text(json.dumps(proof,indent=2),encoding='utf-8')
+print(json.dumps({'result':proof['result'],'target':m.EXPECTED,'temporary_grants_revoked':len(grants),'active_writes':0,'visual_pending':True}))
diff --git a/tools/opportunity-workflow-territory-tasks-http-qa.py b/tools/opportunity-workflow-territory-tasks-http-qa.py
new file mode 100644
index 00000000..88f203b9
--- /dev/null
+++ b/tools/opportunity-workflow-territory-tasks-http-qa.py
@@ -0,0 +1,63 @@
+"""Focused live QA checks for primary location and task lifecycle; no active target."""
+import importlib.util
+import json
+import uuid
+from pathlib import Path
+from datetime import datetime, timezone
+
+spec = importlib.util.spec_from_file_location('opportunity_workflow_http_qa', Path(__file__).with_name('opportunity-workflow-http-qa.py'))
+m = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(m)
+m.path = m.PRIVATE / 'opportunity-workflow-territory-tasks-http-qa.json'
+proof = m.proof
+
+def task(props, id):
+ return next(t for t in props['workflowTasks'] if t['id'] == id)
+
+try:
+ id, payload, document = m.create('investment_project')
+ original = m.page(m.promoter, id)['canonicalOptions']['resources']['locations'][0]['payload']
+ districts = m.promoter.call('GET', '/minhas-oportunidades/territory-options?type=district&parent_id=' + original['province_id'])['data']
+ secondary = next(d for d in districts if d['id'] != original['district_id'])
+ extra = m.promoter.call('POST', f'/minhas-oportunidades/{id}/resources/locations', {'etag': m.page(m.promoter, id)['etag'],
+ 'creation_key': str(uuid.uuid4()), 'reason': m.REASON, 'payload': {**original, 'district_id': secondary['id'], 'is_primary': False}}, status=201)
+ payload.update({'location_mode': 'multiple', 'locations': [extra['id'], payload['locations'][0]]})
+ m.save(m.promoter, id, payload)
+ m.transition(m.promoter, id, 'submit')
+ m.transition(m.validator, id, 'start_review')
+ initial_task = m.page(m.validator, id)['profileContext']['review_task_id']
+ m.transition(m.validator, id, 'request_correction', correction_items=['canonical.demand_statement'])
+ assert task(m.page(m.promoter, id), initial_task)['status'] == 'done'
+ payload['demand_statement'] += ' Correção sintética da revisão de tarefa e localização principal.'
+ m.save(m.promoter, id, payload)
+ m.transition(m.promoter, id, 'submit')
+ submitted = m.page(m.promoter, id)
+ assert 'assignment' not in submitted['profileContext']
+ current_task = submitted['profileContext']['review_task_id']
+ assert current_task != initial_task and task(submitted, current_task)['assignee_user_id'] is None
+ m.transition(m.validator, id, 'start_review')
+ m.review(id, document)
+ m.transition(m.publisher, id, 'publish')
+ published = m.page(m.promoter, id)
+ assert published['record']['primary_territory_id'] == original['district_id']
+ assert published['record']['district'] != secondary['name']
+ m.transition(m.publisher, id, 'suspend')
+ assert all(t['status'] == 'done' for t in m.page(m.promoter, id)['workflowTasks'])
+ proof['primary_and_tasks'] = {'id': id, 'primary_reference_second_in_array': True, 'published_primary_id': original['district_id'],
+ 'correction_closed_previous_review': True, 'resubmission_unassigned_new_task': True, 'suspension_no_open_tasks': True}
+
+ rejected, rp, rd = m.create('real_estate')
+ m.transition(m.promoter, rejected, 'submit')
+ rejected_task = m.page(m.promoter, rejected)['profileContext']['review_task_id']
+ m.transition(m.validator, rejected, 'reject')
+ assert task(m.page(m.promoter, rejected), rejected_task)['status'] == 'done'
+ proof['rejection_task'] = {'id': rejected, 'review_closed_with_reason': True}
+ proof['result'] = 'passed'
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ print(json.dumps({'result': 'passed', 'target': m.EXPECTED, 'primary_case_id': id, 'rejected_case_id': rejected,
+ 'visual_pending': True, 'active_writes': 0}))
+except Exception:
+ proof['result'] = 'failed'
+ raise
+finally:
+ m.persist()
diff --git a/tools/opportunity-workflow-verify-qa.php b/tools/opportunity-workflow-verify-qa.php
new file mode 100644
index 00000000..a6eab81c
--- /dev/null
+++ b/tools/opportunity-workflow-verify-qa.php
@@ -0,0 +1,58 @@
+make(Kernel::class)->bootstrap();
+$identity = portalQaAssertTarget($target);
+config(['portal.profile_access_enabled' => true, 'portal.opportunity_specialized_drafts_enabled' => true]);
+$directory = $root.'/storage/app/private/investmoz-v2/portal-audit';
+$actors = json_decode(file_get_contents($directory.'/profiles-v1-actors-private.json'), true, 512, JSON_THROW_ON_ERROR);
+$promoter = User::whereKey($actors['promoter']['id'])->firstOrFail();
+throw_unless($promoter->id === 21 && str_ends_with($promoter->email, '@example.invalid'), RuntimeException::class, 'Synthetic QA actor mismatch');
+$label = 'Promotor QA — conta sintética 21';
+if ($promoter->name !== $label) {
+ $before = $promoter->name;
+ $promoter->name = $label;
+ $promoter->save();
+ app(PortalProfileAccess::class)->audit($promoter, 'qa_fixture_labeled', ['actor_id' => $promoter->id, 'before' => $before, 'after' => $label, 'reason' => 'Identificação inequívoca do ensaio QA; sem alterar identidade/permissões']);
+}
+DB::beginTransaction();
+DB::statement('SET TRANSACTION READ ONLY');
+$proof = json_decode(file_get_contents($directory.'/opportunity-workflow-http-qa.json'), true, 512, JSON_THROW_ON_ERROR);
+$result = ['target' => $identity, 'captured_at' => gmdate('c'), 'active_writes' => 0, 'visual_pending' => true,
+ 'promoter_qa' => ['id' => $promoter->id, 'name' => $promoter->name, 'mfa_confirmed' => $promoter->two_factor_confirmed_at !== null, 'contexts' => app(PortalProfileAccess::class)->navigation($promoter)['contexts']],
+ 'categories' => [], 'five_phases_nineteen_steps_preserved' => true];
+foreach ($proof['cases'] as $case) {
+ $record = Opportunity::whereKey($case['id'])->firstOrFail();
+ $row = ['id' => $record->id, 'category' => $case['category'], 'working_state' => app(PortalProfileAccess::class)->state($record), 'publication_status' => $record->status];
+ try {
+ $snapshot = app(OpportunityCanonicalContract::class)->validateSubmission($record);
+ $row['canonical_validation'] = 'passed';
+ $row['payload_sha256'] = $snapshot['hash'];
+ $row['resources'] = array_map('count', $snapshot['resources']);
+ $row['country'] = array_map(fn ($l) => $l['payload']['country_code'], $snapshot['resources']['locations']);
+ } catch (ValidationException $error) {
+ $row['canonical_validation'] = 'blocked';
+ $row['missing'] = array_keys($error->errors());
+ }
+ $result['categories'][] = $row;
+}
+$docIds = DB::table('opportunity_documents')->whereIn('opportunity_id', array_column($proof['cases'], 'id'))->pluck('document_id')->all();
+$imageIds = DB::table('opportunity_images')->whereIn('opportunity_id', array_column($proof['cases'], 'id'))->pluck('document_id')->all();
+$result['document_scans'] = DB::table('documents')->whereIn('id', [...$docIds, ...$imageIds])->get(['id', 'media_type', 'sha256', 'malware_scanned_sha256', 'malware_scan_status', 'malware_engine', 'storage_encryption']);
+$result['territories'] = ['registered' => DB::table('geo_locations')->whereNull('deleted_at')->count(), 'geometries' => DB::table('geo_geometries')->count(), 'visual' => 'pending'];
+$result['task_counts'] = DB::table('tasks')->where('source_system', 'opportunity-workflow')->selectRaw('status,count(*) as total')->groupBy('status')->pluck('total', 'status');
+DB::rollBack();
+file_put_contents($directory.'/opportunity-workflow-verification-qa.json', json_encode($result, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode(['target' => $identity, 'promoter_qa_id' => $promoter->id, 'categories' => array_count_values(array_column($result['categories'], 'canonical_validation')), 'active_writes' => 0, 'visual_pending' => true]).PHP_EOL;
diff --git a/tools/portal-audit-dashboard-docs.py b/tools/portal-audit-dashboard-docs.py
new file mode 100644
index 00000000..07d48c96
--- /dev/null
+++ b/tools/portal-audit-dashboard-docs.py
@@ -0,0 +1,107 @@
+"""Add current C43/C44 evidence without replacing historical audit sections."""
+import json
+import re
+from pathlib import Path
+
+root = Path(__file__).resolve().parent.parent
+docs = root / 'docs/investmoz/v2/auditoria-portal'
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+runtime = json.loads((private / 'investor-path-qa-runtime.json').read_text())
+projection = json.loads((private / 'pedidos-abertos-projection.json').read_text())
+marker = 'qa-dashboard-20261010'
+
+
+def readable(body):
+ # Preserve exact identifiers/URLs while spacing numerical evidence and prose.
+ tokens = []
+ pattern = r'`[^`]+`|https?://[^\s;),]+|[0-9a-f]{64}|[\w./-]+\.(?:json|php|xml|tsx|ts|md)|AUD-[A-Z]+-\d+|C\d+|\bI[0-3]\b|\bP[0-2]\b|realEstatePatch|Opportunity[A-Za-z]+'
+ def keep(match):
+ tokens.append(match.group())
+ return '\x00'+str(len(tokens)-1)+'\x00'
+ body = re.sub(pattern, keep, body)
+ body = re.sub(r'(?<=[A-Za-zÀ-ÿ])(?=\d)|(?<=\d)(?=[A-Za-zÀ-ÿ])', ' ', body)
+ body = re.sub(r'([,;:])(?=[A-Za-zÀ-ÿ\d])', r'\1 ', body)
+ body = re.sub(r'([,;:])(?=\x00|\()', r'\1 ', body)
+ body = re.sub(r'(?<=[A-Za-zÀ-ÿ])(?=\x00)', ' ', body)
+ body = re.sub(r'\.([A-ZÀ-Ÿ])', r'. \1', body)
+ for old, new in {'QA e': 'QA e', 'QAflag': 'QA flag', 'QA/backend': 'QA/backend', 'sótrue': 'só true', 'porformulário': 'por formulário', 'empreparação': 'em preparação', 'schemaíntegro': 'schema íntegro', 'àgestão': 'à gestão', 'daQA': 'da QA', 'noativo': 'no ativo', 'doativo': 'do ativo', 'semduplicar': 'sem duplicar', 'seativo': 'se ativo', 'MFA em': 'MFA em', 'flagfalse': 'flag false', 'codeQA': 'código QA', 'workflow completo': 'workflow completo', 'statusarchived': 'status archived', 'volta adraft': 'volta a draft', 'labelCriar': 'label Criar', 'dossiersprivados': 'dossiers privados', 'tipos/enums': 'tipos/enums', 'sem publicação': 'sem publicação', 'no management_draft': 'no management_draft', 'MFAprévia': 'MFA: prévia', 'antes deaceitação': 'antes de aceitação', 'provas porversão/perfil': 'provas por versão/perfil', 'Dow nsomente': 'Down somente', 'Downsomente': 'Down somente', 'Não há hotfile/cacheconfig': 'Não há hotfile/cache de configuração', 'capturas sanitizadas': 'capturas sanitizadas'}.items():
+ body = body.replace(old, new)
+ for old, new in {'transaçãoSQL': 'transação SQL', 'GestoresQA': 'Gestores QA', 'InvestidoresQA': 'Investidores QA', 'emailverificado': 'email verificado', 'possuiMFA': 'possui MFA', 'títuloGestão': 'título Gestão', 'antigaCriar': 'antiga Criar', 'menuPainel': 'menu Painel', 'nofim': 'no fim', 'comoCriar': 'como Criar', 'rótuloNova': 'rótulo Nova', 'emportal.managers': 'em portal.managers', 'CorreçãoQA': 'Correção QA', 'atalhosGestão': 'atalhos Gestão', 'açãoarchive': 'ação archive', 'emstatus': 'em status', 'usaflagsfalse': 'usa flags false', 'usaassets': 'usa assets', 'versãoInertia': 'versão Inertia', 'dessemanifesto': 'desse manifesto', 'bootHTTP': 'boot HTTP', 'filtroarchived': 'filtro archived', 'OportunidadeQA': 'Oportunidade QA', 'oportunidadeQA': 'oportunidade QA', 'IDestável': 'ID estável', 'draftexistente': 'draft existente', 'patchmerge': 'patch merge', 'nomeadosDashboard': 'nomeados Dashboard', 'buildQA': 'build QA', 'ePHPStan': 'e PHPStan', 'novoPDF': 'novo PDF', 'ProvaClamD': 'Prova ClamD', 'porID': 'por ID', 'apenasAPI': 'apenas API', 'eativação': 'e ativação', 'tarefasQA': 'tarefas QA', 'antes de': 'antes de', 'code/assets': 'código/assets', 'no/dashboard': 'no /dashboard', 'apontava/investidor': 'apontava /investidor', 'emportal': 'em portal', 'Lista integral legível': 'Lista integral legível', 'gestorautenticado': 'gestor autenticado', 'configuração ativa': 'configuração ativa', 'somente se': 'somente se', 'PORTAL': 'PORTAL', 'code_hash': 'code_hash'}.items():
+ body = body.replace(old, new)
+ return re.sub(r'\x00(\d+)\x00', lambda m: tokens[int(m[1])], body)
+
+
+def insert(path, body):
+ text = path.read_text(encoding='utf-8-sig')
+ text = re.sub(r'\n.*?\n', '\n', text, flags=re.S)
+ headline, rest = text.split('\n', 1)
+ block = '\n\n'+readable(body.strip())+'\n\n**Histórico preservado:** os blocos anteriores a C43/C44 abaixo conservam as suas fontes e provas. Os seus hashes/ready/contagens não certificam a revisão atual; a primeira adaptação imobiliária não equivale ao schema integral nem ao workflow.\n\n'
+ path.write_text(headline+'\n'+block+'\n'+rest.lstrip('\n'), encoding='utf-8')
+
+
+facts = '''QA exclusiva:http://127.0.0.1:18097, alvo real `desk_restore_20261009_174726_test:55441`. Ativo consultado por transaçãoSQL READ ONLY;0escritas/instalações/publicações ativas. Cinco fases/19etapas,5dossiers/95etapas e393geometrias QA preservados. C37 e aceitação visual permanecem abertos.
+
+GestoresQA14/17 têm emailverificado+`manage-portal`; gestor17 possuiMFA normal. InvestidoresQA13/18 não têm gestão. No ativo, a leitura confirmou contas2/13 autorizadas,020000instalada e030000ausente; o dashboard ativo contém títuloGestão de Oportunidades e ação antigaCriar oportunidade. Não há hotfile/cacheconfig/cache de rotas a explicar a ausência. URL configurado ativo:http://portal-investidor.test; **URL/conta da sessão reportada ainda desconhecidos**, sem atribuição especulativa de causa a essa conta.'''
+evidence = '''- `dashboard-active-readonly.json`:configuração/contas elegíveis/instalação/manifesto ativo, sem bootHTTP/escrita de sessão no ativo.
+- `dashboard-opportunities-http-qa.json`:links obtidos do dashboard→gestão→create→201→GET→logout/nova sessão→GET→PUT→archive→filtroarchived→restore→GET. OportunidadeQA13,IDestável/quatro eventos,12originais e relações/documentos/dossiers preservados;6publicadas mantidas;outra conta403.
+- `dashboard-manager-mfa-http-qa.json`:gestor17,MFA em duas sessões→dashboard→gestão→recuperação/reload→logout;0alterações de registos. `dashboard-navigation-catalogue-qa.json`:menuPainel da gestão→/dashboard,dossiers privados→/investidor,atalhos únicos e ausência de gestão para investidor.
+- `real-estate-draft-http-qa.json`:outra oportunidadeQA14,rascunho imobiliário parcial no draftexistente→nova sessão→patchmerge→cinco422sem mutação→outsider403;schema normativo SHA9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0.
+- `dashboard-real-estate-qa.xml`:casos nomeadosDashboardOpportunityAccessTest/OpportunityManagementTest/OpportunityRealEstateDraftTest,8ensaios/201asserções. Typecheck,buildQA ePHPStan dirigidos passaram; contagem não substitui os critérios visuais.
+- `resource-originals-preservation-http-qa.json`:cinco binários anteriores preservados e novoPDF válido recuperado/parseado,0novos recursos. ProvaClamD real anterior mantida; não afirma novo scan das derivadas nem renderização.
+- `dashboard-matrix-reconciliation-qa.json` e `pedidos-abertos-projection.json`:fontes/trechos/IDs/versões preservados,3354requisitos/linhas e5830ocorrências;3349abertos apresentados uma vez cada. EstadoAUD-OP-04 passa de não implementado a parcial; nenhum requisito global encerrado.'''
+causes = '''**C43 — causas encontradas no código/compilação:**(1)AppSidebar mostrava só o primeiro filho de cada grupo, descartando oportunidades;(2)menuPainel apontava/investidor mesmo para gestor;(3)dashboard de gestão colocava criação nofim comoCriar oportunidade, sem rótuloNova oportunidade. A secção de gestão só é devolvida pelo backend a contas verificadas emportal.managers; o seu ocultamento para investidor é autorização esperada, não motivo para conceder perfil administrativo.
+
+CorreçãoQA:atalhosGestão de Oportunidades/Nova oportunidade no início do dashboard,sidebar/menu agrupado;Painel da gestão→/dashboard,dossiers→/investidor. Nova açãoarchive conserva o rascunho emstatusarchived/deleted_at=null;delete/exclusão lógica mantém o contrato anterior. Restauro volta adraft,ID/histórico intactos,sem publicação. Código usaflagsfalse por omissão; QA usaassets `public/build-qa-opportunities`, versãoInertia dessemanifesto. **`public/build` ativo manteve SHA75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94.** Recursos030000não são requisito para navegar/criar rascunho básico.
+
+**C44 — progresso específico:**primeiro adaptador imobiliário aceita campos fornecidos nas24propriedadesrealEstatePatch,validando tipos/enums/limites/UUID e recusando campos desconhecidos/de resposta. Guarda/merge privadamente no management_draft atual. Ainda faltam formulário especializado,vínculos canónicos,condições finais/Create/Response,DUAT/transação e workflow. Nenhuma coleção/tabela paralela,renumeração ou decisão externa criada. O.source.json conserva o retrato histórico da extração, não certifica o estado runtime atual.'''
+groups = '''| Grupo de trabalho dos abertos | Requisitos | O que falta / próxima ação |
+| --- | ---: | --- |
+| Não implementados |145|Workflow integral segregado;rascunhos incompletos procura/capacidade e jornadas educativas ainda por fazer;demais critérios específicos não implementados no relatório porID. Implementar workflow sobre draft/auditoria após contratos/gates;educação não começa enquanto prioridades abertas.|
+| Parciais |3183|Contrato imobiliário apenasAPI;DUAT/transações/campos/regras finais e vínculos;cartografia31distritos/157postos/mapas por consumidor;relações/citações;acervo/PDFs/partilhas/derivadas;parâmetros fiscais;negócios/direitos/mandatos;reconciliação documental/UX eativação. Inclui4decisões com estado original,sem bloquear tarefasQA independentes.|
+| Preparados emQA |19|Escopos concretos de rascunhos/recursos/maturidade,países/origem/estatísticas,seletor provincial,Balcão/percurso/CRM/orientação/simulador/parceria/fundiário/importação privada com provasQA. Completar critérios restantes na interface e operações/tipos ainda abertos;ativação permanece separada. Não são19requisitos globais concluídos.|
+| Instalados com falha de acesso |2|AUD-DASH-01(C43) eAUD-UI-01(C37/inspeção). Código/backendQA corrigidos nos escopos descritos;identificar sessão reportada e demonstrar dashboard/cliques e loginA/B completos. Confirmar visualmente sem conceder gestão ao investidor.|
+
+**Lista integral legível:**http://127.0.0.1:18097/qa-auditoria/pedidos-abertos,gestorQA14/17.3349cartões,um porID,com pedido,lacuna,próxima ação,critério,fontes/versões/evidências e filtros de grupo/módulo. Vista derivada da [matriz única](matriz-requisitos.csv),sem edição nem estados paralelos;investidor403. Os grupos são editoriais,distintos dos estados canónicos:3199parciais,145não implementados,4decisões,1implementado não ativado,5concluídos de âmbito restrito.
+
+Decisões humanas preservadas:pares exatos das6oportunidades com âncoras/clusters;identidade/termos/contactos do operador;URLs/serviços/responsáveis institucionais;modelo/indicadores/baseline de sucesso. Não reabrir aceitação das fontes oficiais;não inventar pares,parâmetros ou score.'''
+insert(docs / 'relatorio-executivo.md', '## Acesso à Gestão de Oportunidades — loteC43/C44,10/10/2026\n\n'+facts+'\n\n'+causes+'\n\n'+evidence+'\n\n'+groups+'\n\nVisual pendente:[roteiro curto](demonstracao-dashboard-oportunidades.md). API/persistência/assets são provas separadas de interface;nenhum clique automatizado/cenárioA/B visual foi alegado.')
+insert(docs / 'backlog.md', '## Prioridade corrente:Gestão de OportunidadesC43 —10/10/2026\n\n'+groups+'''
+
+Ordem executável restante:1)incorporar ensaio visualC43 e corrigir reprodução;2)formulário/bindings/condições finais imobiliárias;3)adaptadoresDUAT/transação;4)gates e workflow segregado,sem autoaprovação;5)continuar correspondências/cadastros/mapas,países/origem porformulário e operações documentais independentes. C37 continua pendente,sem repetir login do investidor neste lote;não iniciar jornadas educativas novas. Detalhes/ações por cadaID estão na vista integral.
+
+AceitaçãoC43:gestor17/MFA parte de/dashboard→cliques→rascunho→guarda→outra sessão→recupera→edita→arquiva→restaura;feedback/ID/filtro/histórico visíveis;outra conta403;dossier privado e público intactos. CritériosAPI satisfeitos não encerram o critério de interface.''')
+insert(docs / 'casos-reproducao.md', '## Casos adicionaisC43/C44 —10/10/2026\n\n'+causes+'''
+
+C43,reprodução de código/assets:seguirPainel do catálogo com gestor→/investidor;na sidebar,grupoGestão→primeiro filho/interests apenas;no/dashboard a criação está nofim e tem labelCriar oportunidade. Esperado:gestor chega ao seu dashboard e encontra Gestão/Nova sem URL decorado;investidor conserva área privada. Observado:links omitidos/destino partilhado/nome diferente. Evidência do utilizador ainda sem URL/conta;não se afirma que o seu perfil é o motivo. Também havia somenteExcluir rascunho no rascunho inicial,com delete→deleted_at em vez dearchive→statusarchived;corrigido separadamente sem alterardelete.
+
+C44,reprodução anterior por inspeção:categoriareal_estate disponível,mas payloadreal_estate não fazia parte dos campos validados/persistidos. Esperado:guardar dados parciais e recuperar privadamente. Correção limitada:adaptador24propriedadesPatch;cinco negativos HTTP reais422sem mutação. Não se inventou ensaioHTTP pré-correção nem se declarou o contrato integral concluído.
+
+'''+evidence)
+plan = f'''## Sequência adicionalC43/C44 —10/10/2026
+
+Preparação apenas;nenhuma ativação autorizada/executada. Fingerprints correntes:percurso`{runtime['code_hash']}`,recursos`{runtime['resource_code_hash']}`,cartografia`{runtime['geometry_code_hash']}`. Provasready anteriores ficam históricas;nenhuma candidata final.
+
+1. ConcluirC43/visuaisC37/A-B e consumidores;registar reprodução/correção,fixar revisão+manifestos. Renovar backupDB/ficheiros/chaves/originais e restauro numa novaQA guardada,conferindoIDs/relações/hashes/schema. Não forçar contagens históricas288tabelas/5ficheiros.
+2. Disponibilizar código eassets ativos dessa revisão aprovada,configuração reconciliada e cache conferida. Atalhos/arquivo usam`PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`;estáfalse no ativo e sótrue naQA. **Nenhuma migration nova paraC43 ou primeiro draft imobiliário.**020000já instalada:não repetir. Antes de habilitar,conferir gestor(emailverificado+allowlist),rotas e manifesto realmente servido. Rollback:flagfalse e código/assets compatíveis;preservar drafts/estadoarchived/auditoria.
+3. Recursos:gestorautenticado GET/POST`/management/opportunity-resources-install`somente se030000ausente.3tabelas de associação+1coluna documents+função/3triggers;0recursos/originais criados automaticamente. ClamD/GD exigidos pelas operações binárias afetadas,sem bloquear rascunho/metadados. Downsomente vazio;após uso retirar disponibilidade sem eliminar originais/dados.
+4. Percurso:GET/POST`/management/balcao-install`somente para migrationspendentes190000;2colunas+1definição imutável,0conversões/dossiers/etapas. Disponibilização`INVESTOR_PATH_ENABLED`separada,depois deaceitação/instalação;reversão porflagpreserva19etapas/5fases,IDs/resultados/documentos/consentimentos.
+5. Cartografia:gestor/MFAprévia/crosswalk/hash→aplicar níveis1→2→3 semduplicar. Seativo continuar0 ecorrespondênciasiguais,previsão393limitesinternos=11províncias+128distritos+254postos;0territórios novos,31/157pendentes. Publicação dascamadasseparada. Reversão3→2→1somente novas intactas/não usadas,nem publicadas;guardar originais/hash/crosswalk/receipts e relações.
+6. Contratos especializados:`PORTAL_OPPORTUNITY_SPECIALIZED_DRAFTS_ENABLED`ficafalse no ativo. **Não habilitar com este loteAPI parcial.**Completar formulário/bindings/condições finais/DUAT/transação/workflow e provas porversão/perfil;depois planopróprio na mesma auditoria. Desligarflag conservaJSON privado;rollback de código deve manter chave/payloads sem descartá-los. Instalar recursos ou importarcartografia não valida/submete/aprova/publica contrato nem ativa cálculo fiscal.
+
+Plano detalhado anterior conservado abaixo;aplicação documental ativa autenticada,scan próprio dasderivadas e operação permanenteClamD continuam dependências específicas.
+'''
+insert(docs / 'plano-ativacao.md', plan)
+insert(docs / 'cobertura-percursos-i0-i3.md', '## Cobertura adicional:dashboard e draft imobiliário —10/10/2026\n\n'+evidence+'\n\nGestão desde/dashboard:API/destinos reais/gravação/novasessão/recuperação/arquivo/restauro demonstrados;interfacepending. Formulário especializado imobiliário ausente;24campos dePatch são adaptaçãoAPI parcial. Nenhuma cobertura cartográfica/países/origem/documental anterior promovida por esses ensaios. Gestor17/MFA distinto do investidor18;C37 eA/B visuais permanecem abertos.')
+insert(docs / 'execucao-percurso-i1-i3.md', '## Continuação independenteC43/C44 —10/10/2026\n\n'+facts+'\n\n'+evidence+'\n\nRevisão atual não candidata;nenhuma aceitação integralI1–I3 por contagem de testes. Cadastro básico de oportunidades não é dossier privado;operaçãoQA13 não criou dossier/etapa nem alterou as6oportunidades publicadas. Rascunho imobiliárioQA14 não é decisão externa nem contrato completo.')
+insert(root / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', '## Estado corrente:acesso ao dashboardC43 —10/10/2026\n\n'+causes+'\n\n'+facts+'\n\n[Ensaio desde o dashboard](auditoria-portal/demonstracao-dashboard-oportunidades.md),[matriz única](auditoria-portal/matriz-requisitos.csv),[pedidos abertos/backlog](auditoria-portal/backlog.md),[evidências](auditoria-portal/relatorio-executivo.md). API/persistência/assetsQA demonstrados;visual eativação pendentes.393geometrias e schema110defs não encerram o cadastro funcional.')
+path = private / 'investor-path-evidence.json'
+evidence_json = json.loads(path.read_text())
+evidence_json['code_hash'] = runtime['code_hash']
+evidence_json['resource_code_hash'] = runtime['resource_code_hash']
+evidence_json['geometry_code_hash'] = runtime['geometry_code_hash']
+evidence_json['dashboard_increment'] = {'cases': ['C43', 'C44'], 'qa_proofs': ['dashboard-opportunities-http-qa.json', 'dashboard-manager-mfa-http-qa.json', 'dashboard-navigation-catalogue-qa.json', 'real-estate-draft-http-qa.json', 'dashboard-real-estate-qa.xml'], 'visual_passed': False, 'active_enabled': False, 'canonical_matrix_requirements': 3354, 'open_requirements': 3349}
+for key in ['integrated_ui_ab_passed', 'candidate_revision_fixed', 'activation_ready', 'active_activation_authorized', 'c37_browser_acceptance_passed']:
+ evidence_json[key] = False
+evidence_json['current_active_backup_compatibility_renewal_required'] = True
+path.write_text(json.dumps(evidence_json, indent=2, ensure_ascii=False), encoding='utf-8')
+print(json.dumps({'canonical_matrix_preserved': True, 'current_reports_updated': 7, 'open_requirements': projection['open_requirements'], 'active_writes': 0}))
diff --git a/tools/portal-audit-dashboard-update.py b/tools/portal-audit-dashboard-update.py
new file mode 100644
index 00000000..76d684e1
--- /dev/null
+++ b/tools/portal-audit-dashboard-update.py
@@ -0,0 +1,93 @@
+"""Reconcile this increment into the existing matrix, preserving source records."""
+import collections
+import csv
+import hashlib
+import json
+import re
+from pathlib import Path
+
+root = Path(__file__).resolve().parent.parent
+docs = root / 'docs/investmoz/v2/auditoria-portal'
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+path = docs / 'matriz-requisitos.csv'
+baseline = private / 'matriz-pre-dashboard-20261010.csv'
+if not baseline.exists():
+ baseline.write_bytes(path.read_bytes())
+with path.open(encoding='utf-8-sig', newline='') as stream:
+ reader = csv.DictReader(stream)
+ fields = reader.fieldnames
+ rows = list(reader)
+source_fields = ['ID', 'Pedido/trecho', 'Fonte/ocorrências', 'Módulo', 'Critério de aceitação', 'Versões divergentes', 'IDs das linhas de origem', 'Quantidade de linhas de origem', 'Critérios e versões por origem (JSON)', 'Consolidação']
+
+
+def source_digest(records):
+ return hashlib.sha256(json.dumps([{key: r[key] for key in source_fields} for r in records], ensure_ascii=False, sort_keys=True).encode()).hexdigest()
+
+
+baseline_rows = list(csv.DictReader(baseline.open(encoding='utf-8-sig', newline='')))
+before_digest = source_digest(baseline_rows)
+assert source_digest(rows) == before_digest and len(rows) == 3354
+assert sum(int(r['Quantidade de linhas de origem']) for r in rows) == 5830
+marker = ' | [QA dashboard 10/10/2026] '
+
+
+def update(id, changes):
+ row = next(r for r in rows if r['ID'] == id)
+ for key, value in changes.items():
+ row[key] = row[key].split(marker)[0] + marker + value
+
+
+common = 'dashboard-opportunities-http-qa.json: dashboard→destinos anunciados→create→201→GET→logout/nova sessão→GET→PUT→arquivo→filtro archived→restauro; QA13 mantém ID,4 eventos. dashboard-manager-mfa-http-qa.json: gestor17 MFA em duas sessões/reload/logout,0 registos alterados. 12 oportunidades anteriores, relações/documentos/dossiers preservados por SHA;6 publicadas mantidas. browser_visual_observed=false.'
+active = 'Leitura SQL REPEATABLE READ READ ONLY10/10/2026: investemoz:5432;020000 instalada,030000 ausente;6 oportunidades publicadas. Contas2/13 autorizadas e verificadas. Manifesto ativo75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94 preservado;flag do incremento false. Perfil/URL da sessão reportada ainda não confirmados.'
+update('AUD-OP-01', {
+ 'Implementação encontrada': 'OpportunityManagement existente; archive explícito no estado archived distinto de delete/deleted_at, com ETag/razão/confirmação/auditoria/restauro. Flag QA; nenhum schema/cadastro paralelo.',
+ 'Disponibilidade ativa': active,
+ 'Evidência funcional': common,
+ 'API': '201 criação/replay;200 GET/PUT/lifecycle;422 sem confirmação;409 conflito;403 outro perfil. Nova ação archive só com configuração do incremento.',
+ 'Gravação': 'QA13: draft→edição→archived(deleted_at=null)→draft;4 eventos,ID/histórico preservados,0 publicação.',
+ 'Recuperação': 'GET por ID e filtro archived; nova sessão do gestor14 e gestor17/MFA recuperam QA13.',
+ 'Interface': 'Código/assets QA em build-qa-opportunities; HTML da página usa manifesto QA. Dashboard/sidebar recebem Gestão de Oportunidades/Nova oportunidade. Sem clique/renderização de navegador demonstrados.',
+ 'Resultado apresentado': 'Mensagens/controlos preparados;props devolvem título editado/archived/draft. Resultado visual pendente.',
+ 'Lacuna': 'C43: navegação e archive corrigidos em QA; fecho exige dashboard→cliques→recuperação/edição/arquivo/restauro renderizados. Cadastro modular integral/workflow ainda pendentes.',
+ 'Dependência': 'Perfil exato da sessão reportada; navegador QA e futura ativação separada. Não repetir020000 nem exigir030000 para rascunho básico.'})
+update('AUD-DASH-01', {
+ 'Implementação encontrada': 'C43: AppSidebar omitia todos os filhos exceto primeiro destino de cada grupo; Painel apontava/investidor também para gestor; criação no fim com labelCriar oportunidade. Atalhos/dashboard/menu agrupado corrigidos reutilizando props autorizadas; Painel da gestão→/dashboard,dossiers→/investidor. FlagQA e build separado; área privada preservada.',
+ 'Disponibilidade ativa': active,
+ 'Evidência funcional': common,
+ 'Interface': 'AppSidebar+dashboard corrigidos; validação visual do layout/atalhos/teclado/móvel pendente. API e HTML não equivalem a clique.',
+ 'API': 'Links descobertos da resposta de /dashboard e seguidos no servidor18097. GestoresQA14/17 autorizados;QA13/18 não são gestores; investidor/unverified/guest não ganham gestão.',
+ 'Gravação': 'Percurso de oportunidade QA13 conserva dossier privado e seis versões públicas; testes de negativa preservam dados.',
+ 'Recuperação': 'Nova sessão/reload do gestor17 com MFA mantém oportunidade13; outra conta403.',
+ 'Resultado apresentado': 'Manifesto ativo preservado; HTML QA aponta build-qa-opportunities e version hash próprio. Perfil da sessão do relato ainda desconhecido; sem atribuição de causa a essa conta.',
+ 'Lacuna': 'C43 corrigido em QA/backend/assets, sem ativação; interface e identidade da sessão reportada pendentes. C37/A-B e demais ações do dashboard continuam abertos.',
+ 'Dependência': 'Ensaio visual autenticado em18097. Gestor requer email em portal.managers+verificado; não elevar investidor18 por causa da ausência do menu.'})
+update('AUD-UI-01', {'Evidência funcional': common, 'Lacuna': 'Navegador automático sem apps/browsers; C43 tem protocolo/persistência/assets demonstrados, visual pendente. C37 mantém pendência anterior sem novo login do investidor18. Roteiro curto de gestão com perfil17 em demonstracao-dashboard-oportunidades.md.', 'Interface': 'C43/gestão e C37/investidor são ensaios independentes; ambos exigem navegador, não foram encerrados por HTTP.'})
+update('AUD-OP-04', {
+ 'Implementação encontrada': 'OpportunityRealEstateDraft valida campos fornecidos nas24 propriedades realEstatePatch do schema normativo. OpportunityManagement guarda/merge no management_draft existente, sem coluna/tabela nova. Flag especializada só QA. Primeira parte de um contrato, não9contratos completos.',
+ 'Evidência funcional': 'real-estate-draft-http-qa.json: QA14(diferente de user14),201/replay mesmoID→GET→nova sessão→patch merge→cinco422 sem mutação→outra conta403;originais/dossiers preservados. OpportunityRealEstateDraftTest: versão publicada intacta e sem dados especializados na API pública.',
+ 'API': 'real_estate parcial no POST drafts/PUT draft existente, com tipos/enums/limites/UUID e campos de resposta recusados. Condições finais/Create/Response/referências canónicas NÃO estão completas.',
+ 'Gravação': 'QA14: contrato parcial imobiliário em management_draft; PATCH preserva valores anteriores; nenhum estado submetido/aprovado/publicado.',
+ 'Recuperação': 'GET edit devolve values.real_estate depois de logout/nova sessão; outro perfil403.',
+ 'Interface': 'Formulário especializado ainda ausente; nenhuma prova visual ou contrato integral atribuído ao adaptador API.',
+ 'Resultado apresentado': 'Campos privados recuperados por props; ainda não há apresentação/edição por controlos especializados.',
+ 'Lacuna': 'Completar formulário, vínculos canónicos/documentais, condições finais §26,Create/Response e demais módulos DUAT/transação. Dados parciais guardáveis não validam viabilidade nem decisão externa.',
+ 'Dependência': 'Reutilizar documentos/direitos/objetos/negócios/territórios existentes; não renumerar bigint para exemplosUUID. Sem nova decisão para implementar emQA.'})
+next(r for r in rows if r['ID'] == 'AUD-OP-04')['Estado'] = 'parcial'
+update('AUD-OP-03', {'Lacuna': 'Workflow completo permanece não implementado. Primeira gravação privada imobiliáriaC44 não é revisão/aprovação/publicação. Próximo: gate de completude por versão, autor/revisor distintos, devolver com razão, revisão técnica/jurídica/territorial, aprovação/publicação separadas; preservar versão pública.'})
+update('AUD-OPS-01', {'Evidência funcional': 'dashboard-active-readonly.json reconfirma020000 instalada e030000 ausente,0 escrita ativa;build QA separado,manifesto ativo preservado. Fingerprints incluem dashboard/sidebar/middleware/config/schema/adaptador; evidência anterior ready não certifica esta revisão.', 'Lacuna': 'Revisão candidata não fixada: C37/C43/A-B/consumidores visuais pendentes. Renovar backup/restauro depois desses ensaios. Ativação de atalhos/arquivo e adaptador especializado separada das instalações030000/190000/importação1→2→3/publicação.'})
+update('AUD-DOC-01', {'Evidência funcional': 'Mesma matriz3354requisitos/5830ocorrências preserva fontes/trechos/IDs/versões por SHA; apenasAUD-OP-04 muda não implementado→parcial pelo incremento específicoAPI. Lista integral de3349abertos derivada desta matriz,sem estados independentes nem segunda matriz.'})
+assert source_digest(rows) == before_digest
+old_states = {r['ID']: r['Estado'] for r in baseline_rows}
+state_changes = [r['ID'] for r in rows if r['Estado'] != old_states[r['ID']]]
+assert state_changes == ['AUD-OP-04']
+with path.open('w', encoding='utf-8', newline='') as stream:
+ writer = csv.DictWriter(stream, fieldnames=fields)
+ writer.writeheader()
+ writer.writerows(rows)
+states = collections.Counter(r['Estado'] for r in rows)
+counts = {'requisitos': len(rows), 'linhas_matriz': len(rows), 'linhas_origem': sum(int(r['Quantidade de linhas de origem']) for r in rows),
+ 'por_estado': {state: {'requisitos': n, 'linhas_origem': sum(int(r['Quantidade de linhas de origem']) for r in rows if r['Estado'] == state)} for state, n in states.items()},
+ 'conservation_sha256': before_digest, 'metodo': 'Mesma matriz canónica; requisitos e ocorrências separados; alteração específica de estadoAUD-OP-04 documentada; agrupamento editorial não altera estado.', 'browser_current_version_verified': False}
+(private / 'contagens-requisitos.json').write_text(json.dumps(counts, indent=2, ensure_ascii=False), encoding='utf-8')
+(private / 'dashboard-matrix-reconciliation-qa.json').write_text(json.dumps({**counts, 'state_changes': state_changes, 'sources_versions_preserved': True, 'active_writes': 0}, indent=2, ensure_ascii=False), encoding='utf-8')
+print(json.dumps(counts, ensure_ascii=False))
diff --git a/tools/portal-audit-document-types-qa.py b/tools/portal-audit-document-types-qa.py
new file mode 100644
index 00000000..c3ab93a0
--- /dev/null
+++ b/tools/portal-audit-document-types-qa.py
@@ -0,0 +1,44 @@
+"""Check the exact synthetic PDF fixtures independently; never touches an application DB."""
+import hashlib
+import io
+import json
+import logging
+from pathlib import Path
+import subprocess
+import sys
+
+root = Path(__file__).resolve().parent.parent
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+sys.path.insert(0, str(private / 'pdf-proof-tooling'))
+import pypdf
+
+logging.getLogger('pypdf').setLevel(logging.CRITICAL)
+php = Path.home() / '.config/investmoz/php-8.5.11/php.exe'
+checks = []
+for label, text in [('original', None), ('batch', 'Synthetic QA batch - no official or legal value')]:
+ # All PHP input is fixed QA fixture code, passed as an argv value, never through a shell.
+ argument = '' if text is None else "'" + text + "'"
+ code = "require 'vendor/autoload.php'; echo Tests\\Support\\SyntheticDocument::pdf(" + argument + ');'
+ content = subprocess.run([str(php), '-r', code], cwd=root, check=True, capture_output=True).stdout
+ reader = pypdf.PdfReader(io.BytesIO(content), strict=True)
+ assert len(reader.pages) == 1
+ assert 'no official or legal value' in reader.pages[0].extract_text()
+ path = private / ('synthetic-valid-' + label + '.pdf')
+ path.write_bytes(content)
+ checks.append({'fixture': label, 'sha256': hashlib.sha256(content).hexdigest(), 'bytes': len(content),
+ 'pages': len(reader.pages), 'strict_parse': True, 'text_recovered': True, 'interface_rendered': False})
+
+legacy_header_only = b'%PDF-1.7\nSynthetic web QA only\n%%EOF'
+try:
+ pypdf.PdfReader(io.BytesIO(legacy_header_only), strict=True)
+except pypdf.errors.PdfReadError as error:
+ legacy_result = {'parseable': False, 'failure_class': type(error).__name__, 'origin': 'Historical09/10 header-only fixture in portal-resources-real-http-qa.py, before this increment.'}
+else:
+ raise AssertionError('The legacy header-only negative control unexpectedly parsed.')
+proof = {'scope': 'Independent parser check of the fixture generator used by current document feature tests; not browser rendering or upload on web18097.',
+ 'parser': 'pypdf', 'parser_version': pypdf.__version__, 'fixtures': checks,
+ 'legacy_header_only_control': legacy_result, 'existing_originals_replaced': False,
+ 'database_connection': False, 'active_writes': 0, 'interface_observed': False}
+(private / 'document-types-fixture-qa.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'valid_synthetic_pdf_fixtures': len(checks), 'pages_each': 1, 'legacy_header_only_parseable': False,
+ 'interface_rendered': False, 'existing_originals_replaced': False, 'active_writes': 0}))
diff --git a/tools/portal-audit-geometry-gaps.py b/tools/portal-audit-geometry-gaps.py
index a82b2426..c030cef8 100644
--- a/tools/portal-audit-geometry-gaps.py
+++ b/tools/portal-audit-geometry-gaps.py
@@ -1,40 +1,75 @@
-"""Name every unmatched official feature; supplement the existing audit, not its matrix."""
+"""Reconcile existing named gaps with authenticated QA proof; retain earlier names/counts."""
+import hashlib
import json
-from collections import defaultdict
from pathlib import Path
root = Path(__file__).resolve().parent.parent
private = root / 'storage/app/private/investmoz-v2/portal-audit'
docs = root / 'docs/investmoz/v2/auditoria-portal'
-levels = {}
+proof = json.loads((private / 'geometry-crosswalk-http-qa.json').read_text(encoding='utf-8-sig'))
+preservation = json.loads((private / 'geometry-crosswalk-preservation-qa.json').read_text(encoding='utf-8-sig'))
+consumer_http = json.loads((private / 'geometry-crosswalk-consumers-http-qa.json').read_text(encoding='utf-8-sig'))
+assert proof['applied'] and not proof['published'] and not proof['interface_observed'] and proof['active_writes'] == 0
+assert preservation['target'] == proof['target'] and preservation['catalogue_preserved'] and preservation['original_geometries_preserved'] == 361
+assert consumer_http['target'] == proof['target'] and not consumer_http['applied'] and not consumer_http['interface_observed']
+assert len(consumer_http['consumer_recovery']) == len(consumer_http['public_recovery']) == 32
+plans = {p['level']: p for p in proof['plans']}
+names = {1: 'Províncias', 2: 'Distritos', 3: 'Postos administrativos'}
+gaps, explicit = [], []
for level in [1, 2, 3]:
- source = json.loads((private / f'moz-adm{level}-ine-20190607.geojson').read_text(encoding='utf-8-sig'))
- rehearsal = json.loads((private / f'geometry-qa-adm{level}-import.json').read_text(encoding='utf-8-sig'))
- levels[level] = {r['pcode']: r for r in rehearsal['mappings']}
+ path = private / f'moz-adm{level}-ine-20190607.geojson'
+ assert hashlib.sha256(path.read_bytes()).hexdigest() == plans[level]['source_sha256']
+ source = json.loads(path.read_text(encoding='utf-8-sig'))
+ rows = {r['external_id'].rsplit(':', 1)[1]: r for r in plans[level]['rows']}
for feature in source['features']:
p = feature['properties']
- r = levels[level][p[f'ADM{level}_PCODE']]
- r['parent_name'] = p.get(f'ADM{level - 1}_PT')
- r['province_name'] = p['ADM1_PT']
-
-names = {1: 'Províncias', 2: 'Distritos', 3: 'Postos administrativos'}
-text = ['# Correspondências cartográficas — lacunas por nome', '', 'Complemento de AUD-GEO-02/03 da mesma matriz. Exemplar INE/UNOCHA 07/06/2019 aceite; esperado significa total deste exemplar, não um total administrativo atual certificado. Não converte limites administrativos em disponibilidade de terra.', '', '| Nível | Esperado no exemplar | Resolvido em QA | Pendente |', '| --- | ---: | ---: | ---: |']
-gaps = []
+ r = rows[p[f'ADM{level}_PCODE']]
+ if r.get('correspondence') and r['status'] in ['insert', 'reuse']:
+ explicit.append({'pcode': p[f'ADM{level}_PCODE'], 'source_name': r['name'], 'id': r['location_id'], **r['correspondence']})
+ if r['status'] in ['insert', 'reuse']:
+ continue
+ reason = {'parent_unresolved': 'Pai do exemplar sem correspondência; não associa por nome isolado',
+ 'name_unresolved': 'Nome sem correspondência única sob o pai resolvido',
+ 'ambiguous_name': 'Mais de um cadastro com mesmo nome/pai; ambos preservados',
+ 'invalid_geometry': 'Geometria inválida; original sem reparação silenciosa'}.get(r['status'], r['status'])
+ gaps.append({'level': level, 'name': r['name'], 'pcode': p[f'ADM{level}_PCODE'], 'parent_name': p.get(f'ADM{level-1}_PT'),
+ 'parent_pcode': p.get(f'ADM{level-1}_PCODE'), 'province': p['ADM1_PT'], 'reason': reason, 'status': r['status'], 'candidates': r['candidates']})
+resolved = sum(p['resolved'] for p in plans.values())
+expected = sum(p['expected'] for p in plans.values())
+assert expected - resolved == len(gaps) and preservation['total_active'] == resolved
+text = ['# Correspondências cartográficas — estado atual e histórico', '',
+ '10/10/2026. Complemento de AUD-GEO-02/03 na mesma matriz. QA18097/desk_restore_20261009_174726_test:55441. Esperado refere o exemplar INE/UNOCHA de07/06/2019 aceite, não uma divisão administrativa atual certificada.', '',
+ '| Nível | Esperado | Resolvido QA | Pendente | Incremento sobre09/10 |', '| --- | ---: | ---: | ---: | ---: |']
for level in [1, 2, 3]:
- pending = [r for r in levels[level].values() if not r['matched_id']]
- assert len(pending) == {1: 2, 2: 39, 3: 179}[level]
- text.append(f'| {names[level]} | {len(levels[level])} | {len(levels[level]) - len(pending)} | {len(pending)} |')
- for r in pending:
- reason = 'Nome não tem correspondência única no nível' if level == 1 else ('Pai sem correspondência; não associa por nome isolado' if not levels[level - 1][r['source_parent_code']]['matched_id'] else 'Nome sem correspondência única sob o pai resolvido')
- gaps.append({'level': level, 'name': r['source_name'], 'pcode': r['pcode'], 'parent_name': r['parent_name'], 'parent_pcode': r['source_parent_code'], 'province': r['province_name'], 'reason': reason})
-text += ['', '2/39/179 são pendentes, não importados. Foram resolvidos 361 de 581 elementos: 9+120+232. A repetição do ensaio CLI reutilizou361. Aplicação autenticada e interface têm provas independentes.', '', 'A normalização permite somente caixa e diacríticos. Não decide aliases, divisões recentes, fusões, homónimos ou mudança de pai. Maputo e Maputo City permanecem distintos; não renomear os cadastros existentes para forçar correspondência. Para fechar um alias é necessária a correspondência explícita entre código do exemplar e ID existente, com fundamento e âmbito/edição.', '']
+ p = plans[level]
+ text.append(f"| {names[level]} | {p['expected']} | {p['resolved']} | {p['pending']} | +{p['resolved'] - {1:9,2:120,3:232}[level]} |")
+text += ['', f'**{resolved} resolvidos/{len(gaps)} pendentes, de {expected} elementos.** As 32 novas geometrias são 2+8+22; as 361 anteriores e os 1990 registos territoriais foram preservados no retrato. O seletor recupera 1920 referências de quatro níveis:11+148+437+1324; os 70 países do cadastro não integram esse denominador. Sem geometrias de localidades neste exemplar. Cadastro, geometria autorizada e apresentação funcional são critérios independentes.', '',
+ '## Correspondências explícitas', '', '| INE | Nome do exemplar | Cadastro/código | ID existente | Fundamento |', '| --- | --- | --- | --- | --- |']
+for r in explicit:
+ text.append(f"| {r['pcode']} | {r['source_name']} | {r['target_name']}/{r['target_source_code']} | {r['id']} | {r['basis']} |")
+text += ['', 'Configuração versionada config/geometry-correspondences.php; fonte/hash/edição/nome/código/pai entram na prévia assinada. CódigosINE e workbook não são convertidos aritmeticamente. Zero renomeações, novos territórios, mudanças de pai ou publicação. Cidade De Maputo/MZ0601 é agregado de2019: não se associa a um dos distritos urbanos cadastrados.', '',
+ '## Mandie — ambiguidade preservada', '',
+ 'MZ040402/Mandie sob Guro tem candidatos4944a651-23ec-5d51-a5ff-14b0b53ed672 (source_code02) e ea7be18f-2a93-5416-a07a-c207a700e070 (03). Workbook aceite:MANDIE nas linhas11117 e11138, códigos diferentes. Sufixo do P-code não prova equivalência de códigos. Conferir correspondência documental específica; não fundir cadastros. Não bloqueia correspondentes únicos independentes.', '']
for level in [1, 2, 3]:
items = [r for r in gaps if r['level'] == level]
- text += [f'## {names[level]} — {len(items)} pendentes', '', '| Código do exemplar | Nome exato | Pai | Causa |', '| --- | --- | --- | --- |']
+ text += [f'## {names[level]} — {len(items)} pendentes atuais', '', '| Código | Nome exato | Pai | Causa |', '| --- | --- | --- | --- |']
for r in items:
text.append(f"| {r['pcode']} | {r['name']} | {r['parent_name'] or '—'} | {r['reason']} |")
text.append('')
-text += ['## Lacunas de cobertura além das correspondências', '', '- O exemplar identificado não contém polígonos próprios de localidades; não inventar nem duplicar territórios.', '- Os 1.990 territórios cadastrados e estes581 elementos têm níveis/âmbitos distintos; um não é o denominador do outro.', '- Geometria disponível, acesso autorizado e desenho funcional em cada consumidor são critérios independentes. As361 geometrias permanecem internas em QA; a importação não as publica.', '- O total previsto no ativo é361 somente se a prévia renovada conservar estas correspondências e zero conflitos. Não repetir instalações nem considerar `ready=true` uma importação.', '']
-(docs / 'correspondencias-cartograficas.md').write_text('\n'.join(text), encoding='utf-8')
-(private / 'geometry-named-gaps.json').write_text(json.dumps(gaps, ensure_ascii=False, indent=2), encoding='utf-8')
-print(json.dumps({'expected': 581, 'resolved': 361, 'pending': len(gaps), 'named_gaps': 'correspondencias-cartograficas.md'}))
+text += ['## Provas e critérios abertos', '',
+ '- geometry-crosswalk-http-qa.json: aplicação autenticada/MFA, replay e API do mapa para22postos novos. A tentativa anterior aplicou2províncias+8distritos antes de parar na ambiguidadeMandie; recibos/eventos originais estão na prova de preservação. O tratamento foi corrigido para manter ambiguidades pendentes e importar as correspondências únicas.',
+ '- geometry-crosswalk-preservation-qa.json: alvo guardado,393 internos,32novos,361anteriores/1990cadastros preservados. geometry-consumers-path-qa.json recupera393/393 por serviço READ ONLY e0limites privados públicos. Não é prova de publicação ou desenho.',
+ '- geometry-crosswalk-consumers-http-qa.json: nova consulta dos 32 limites inseridos, pelo endpoint usado pelo componente, recupera 32 para gestor/MFA e nenhum para público; as duas províncias Maputo têm correspondência única por nome exato. Não aplicou outro lote e não demonstra renderização.',
+ '- TerritoryFields e ProvinceSelect partilhados usam os mesmos IDs/endpoints/preview. ProvinceSelect exige nome exato/único; conserva texto histórico e explica ausência. TypeScript/build passam; seleção/gravação/recuperação e Leaflet por consumidor exigem interface.',
+ '- Reversão recusa alteração/publicação/FK e descendentes ativos da edição. Ordem:postos→distritos→províncias, só lotes novos; originais/cadastros/histórico preservados. Identidades revertidas não são ressuscitadas por replay.', '']
+destination = docs / 'correspondencias-cartograficas.md'
+old = destination.read_text(encoding='utf-8-sig')
+marker = '## Histórico09/10 — nomes e contagens anteriores'
+history = old.split(marker, 1)[1].strip() if marker in old else old.strip()
+destination.write_text('\n'.join(text) + '\n' + marker + '\n\n' + history + '\n', encoding='utf-8')
+named = private / 'geometry-named-gaps.json'
+archive = private / 'geometry-named-gaps-20261009.json'
+if named.exists() and not archive.exists():
+ archive.write_bytes(named.read_bytes())
+named.write_text(json.dumps(gaps, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'expected': expected, 'resolved': resolved, 'pending': len(gaps), 'named_gaps': 'correspondencias-cartograficas.md', 'active_writes': 0}))
diff --git a/tools/portal-audit-installation-update.py b/tools/portal-audit-installation-update.py
new file mode 100644
index 00000000..50b37048
--- /dev/null
+++ b/tools/portal-audit-installation-update.py
@@ -0,0 +1,312 @@
+"""Current QA increment in the existing matrix and reports, with source conservation."""
+import collections
+import csv
+import hashlib
+import json
+import re
+import sys
+from pathlib import Path
+from datetime import datetime, timezone
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
+csv.field_size_limit(16 * 1024 * 1024)
+sys.stdout.reconfigure(encoding='utf-8')
+
+def read(name):
+ return json.loads((PRIVATE / name).read_text(encoding='utf-8-sig'))
+
+def readable(text):
+ replacements = {
+ 'ClamDreal': 'ClamD real', 'HTTP18097': 'HTTP 18097', 'HTTP/MFA': 'HTTP com MFA',
+ 'dump consistente→nova base': 'dump consistente → nova base', 'MFA/bytes': 'MFA / bytes',
+ '15inseridos/393reutilizados': '15 inseridos / 393 reutilizados', '15inserts/393reuse': '15 inseridos / 393 reutilizados',
+ '15limites': '15 limites', '393associações': '393 associações', '1990cadastros': '1.990 cadastros',
+ '361geometrias': '361 geometrias', '361originais': '361 originais', '47incrementaisprivados': '47 incrementais privados',
+ '26distritos': '26 distritos', '147postos': '147 postos', '173pendentes': '173 pendentes',
+ '0contas/grants/flags': 'zero contas, atribuições ou flags', '0documentos': 'zero documentos',
+ '3coleções': 'três coleções', '4tabelas+1colunausers+3colunasoportunidades': 'quatro tabelas + uma coluna em users + três em opportunities',
+ '2colunas+1definição publicada19etapas/5fases;0dossiers': 'duas colunas + uma definição publicada de 19 etapas / cinco fases; zero dossiers',
+ '190000faltantes': '190000 faltantes', '0fixtures QA noativo': 'zero fixtures QA no ativo',
+ '2contas explicitamente designadas,3.ºgestor comMFAaprova': 'duas contas explicitamente designadas; um terceiro gestor com MFA aprova',
+ 'porperfil': 'por perfil', 'porformulário': 'por formulário', 'porconsumidor': 'por consumidor',
+ 'futura candidata/ativo apósvisual': 'futura candidata e do ativo após demonstração visual',
+ 'apósvisual': 'após demonstração visual', 'Semvisual': 'Sem demonstração visual', 'semvisual': 'sem demonstração visual',
+ 'porcritério': 'por critério', 'nolote': 'no lote', 'nolhistórico': 'no histórico',
+ 'todosos': 'todos os', 'Todasasfontes': 'Todas as fontes', 'fontes,nomes econtagensanteriores seguemabaixo': 'fontes, nomes e contagens anteriores seguem abaixo',
+ 'umdos': 'um dos', 'usadosimutáveis': 'usados imutáveis', 'perfís': 'perfis',
+ 'nopróprio': 'no próprio', 'doPublicador': 'do Publicador', 'doPromotor': 'do Promotor',
+ 'contas/grants/titulares': 'contas, atribuições ou titulares', 'scanClamD': 'scan ClamD',
+ 'emUI': 'na interface', 'UI.': 'interface.', 'ledger+duascolunas': 'ledger + duas colunas',
+ 'backupDB+originais+runtime/chaveestável': 'backup da base + originais + runtime e chave estável',
+ 'VisualC37/QA21/A-B ecorreções→fixar candidata/hash/manifesta/config': 'Demonstração visual de C37, QA21 e A/B e correções → fixar candidata, hashes, manifesto e configuração',
+ '→backup': ' → backup', '→restauro': ' → restauro', '→scan': ' → scan', '→download': ' → download',
+ '→novaMFA': ' → nova sessão com MFA', '→retry': ' → repetir', '→rollback completo': ' → reversão completa',
+ 'aprovado/configurado': 'aprovado ou configurado', 'mfa': 'MFA',
+ 'prévia/schema/dependências030+020': 'prévia, schema e dependências 030000 + 020000',
+ 'dependências/preview/hash/MFA': 'dependências, prévia, hash e MFA', 'noopsemDDL': 'operação sem alterações DDL',
+ 'noop auditado': 'operação sem alterações, auditada', 'Runtimeestável': 'runtime estável',
+ 'Publicador porversão': 'Publicador por versão', 'arquivo privado QA+runtime': 'arquivo privado QA + runtime',
+ 'confiabilidade': 'credibilidade', 'mostraJSON': 'mostra JSON', 'falha auditiva': 'falha de auditoria',
+ }
+ for old, new in replacements.items():
+ text = text.replace(old, new)
+ return text
+
+checks, http, office = [read(n) for n in ['profile-installation-checks-qa.json', 'profile-installation-http-qa.json', 'opportunity-office-documents-http-qa.json']]
+independent = read('independent-documents-http-qa.json')
+document_verify = read('independent-documents-verification-qa.json')
+geo = read('geometry-crosswalk-v2-http-qa.json')
+preserve = read('geometry-crosswalk-preservation-qa.json')
+active = read('dashboard-active-readonly.json')
+backup = json.loads((PRIVATE.parent / 'portal-profile-installation/readiness.json').read_text(encoding='utf-8-sig'))
+assert all(x['result'] == 'passed' and x['active_writes'] == 0 for x in [checks, http, office])
+assert all(x['result'] == 'passed' and x['active_writes'] == 0 and not x['interface_observed'] for x in [independent, document_verify])
+assert len(independent['land']) == len(independent['room']) == 3 and len(document_verify['documents']) == 6
+assert checks['code_hash'] == http['code_hash'] == backup['code_hash']
+assert geo['applied'] and geo['active_writes'] == 0 and not geo['published']
+assert preserve['catalogue_preserved'] and preserve['original_geometries_preserved'] == 361 and preserve['total_active'] == 408
+assert sum(r['inserted'] for r in geo['results']) == 15 and backup['restore_verified']
+assert active['identity']['read_only'] == 'on' and active['active_writes'] == 0
+
+# Preserve a dedicated receipt of the enlarged scope and all source associations.
+(PRIVATE / 'geometry-crosswalk-v2-preservation-qa.json').write_bytes((PRIVATE / 'geometry-crosswalk-preservation-qa.json').read_bytes())
+plans = {p['level']: p for p in geo['plans']}
+gaps = []
+for level in [1, 2, 3]:
+ source_file = PRIVATE / f'moz-adm{level}-ine-20190607.geojson'
+ assert hashlib.sha256(source_file.read_bytes()).hexdigest() == plans[level]['source_sha256']
+ source = json.loads(source_file.read_text(encoding='utf-8-sig'))
+ rows = {r['external_id'].rsplit(':', 1)[1]: r for r in plans[level]['rows']}
+ for feature in source['features']:
+ p = feature['properties']
+ r = rows[p[f'ADM{level}_PCODE']]
+ if r['status'] in ['insert', 'reuse']:
+ continue
+ gaps.append({'level': level, 'name': r['name'], 'pcode': p[f'ADM{level}_PCODE'], 'parent_name': p.get(f'ADM{level-1}_PT'),
+ 'parent_pcode': p.get(f'ADM{level-1}_PCODE'), 'province': p['ADM1_PT'], 'status': r['status'], 'candidates': r['candidates'],
+ 'reason': {'parent_unresolved': 'Pai ainda sem correspondência; não associar por nome isolado', 'name_unresolved': 'Nome sem correspondência única sob o pai resolvido',
+ 'ambiguous_name': 'Múltiplos cadastros sob o mesmo pai; preservar ambos'}.get(r['status'], r['status'])})
+assert len(gaps) == 173
+named = PRIVATE / 'geometry-named-gaps.json'
+archive = PRIVATE / 'geometry-named-gaps-v1-188.json'
+if named.exists() and not archive.exists():
+ archive.write_bytes(named.read_bytes())
+named.write_text(json.dumps(gaps, ensure_ascii=False, indent=2), encoding='utf-8')
+
+tag = '[Instalação/cartografia QA 10/10/2026] '
+matrix = DOCS / 'matriz-requisitos.csv'
+rows = list(csv.DictReader(matrix.open(encoding='utf-8-sig', newline='')))
+protected = ['ID', 'Pedido/trecho', 'Fonte/ocorrências', 'Critério de aceitação', 'Versões divergentes', 'IDs das linhas de origem', 'Quantidade de linhas de origem', 'Critérios e versões por origem (JSON)']
+before = [{k: r[k] for k in protected} for r in rows]
+
+def append(row, column, value):
+ old = re.sub(r'\s*\|\s*' + re.escape(tag) + r'.*?(?=\s*\|\s*\[|$)', '', row[column], flags=re.S)
+ row[column] = old + ' | ' + tag + readable(value)
+
+entries = {
+ 'AUD-PROFILE-31': ('Instalador autenticado040000: prévia/schema/dependências030+020, hash/reason/MFA, idempotência UUID e auditoria transacional; bootstrap separado e explícito reutiliza PortalSuperusers. Schema parcial bloqueado; rollback vazio/reinstalação e falha de auditoria recuperados em teste isolado.',
+ 'Visual da instalação/bootstrap, designação real dos dois titulares e política da recuperação simultânea; backup da futura candidata/ativo apósvisual. Schema040 jáQA, sem reinstalação destrutiva ou novos titulares no servidor18097.'),
+ 'AUD-OPS-01': ('030→040→190 preservada:030/040/09-190 QA instaladas e ausentes no ativo lido READONLY. GET/POST/management/profile-install disponíveisQA; preparação não instala nem disponibiliza o percurso.',
+ 'Candidata não fixada; visualC37/QA21/A-B, prova ativa de backup/restauro e autorização de ativação futura; não aplicar ativos nesta autorização.'),
+ 'AUD-GEO-02': ('Configcrosswalkv2 conserva Maputo/Matola e acrescenta cinco distritos e três aliases de postos; sete postos exatos resolvem pelos novos pais. Importação autenticada+MFA+replay:15inseridos/393reutilizados, zero publicação/cadastro/reparenting.',
+ '173 correspondências nomeadas:26distritos+147postos. Mandie e agregados/edições divergentes permanecem ambíguos. Fonte2019 não fornece geometrias de localidades ou de parcelas.'),
+ 'AUD-GEO-03': ('QA408 geometrias=11províncias+133distritos+264postos; API do consumidor recupera os15 novos limites. 1990cadastros e361geometrias originais preservados;393associações prévias reutilizadas sem alteração.',
+ 'Seleção/gravação/recuperação/render por consumidor continuam sem ensaio visual. Países/origem/filtros/estatísticas transversais não encerrados pela cartografia ou pelos contratos.'),
+ 'AUD-OP-02': ('DOCX/XLSX OOXML válidos:upload18097→scanClamDreal→download21/24/25;23negado403;delete404/opção retirada→restore→novaMFA/bytes idênticos. PDFs/imagens/derivadas anteriores mantidos, originais preservados.',
+ 'Partilhas/exportações/PDFs derivados e cobertura de todos os consumidores e perfis ainda exigem provas próprias; validação de pacoteOOXML não demonstra renderWord/Excel. Visual documental pendente.'),
+ 'AUD-OP-03': ('Apresentação distingue aprovação interna, versão disponibilizada sob acesso restrito e catálogo público; estado técnico published preservado. Scope efetivo consulta política real do catálogo, não só valor do enum.',
+ 'Visual por perfil/workflow completo emUI pendente; incidentes, reatribuição e recurso integral continuam no backlog existente.'),
+ 'AUD-OP-04': ('Seis contratos semânticos anteriores preservados; DOCX/XLSX e rótulos/Response de âmbito efetivo completados neste lote. Quatro propostas concretas de campos/documentos/gates/versões preparadas no documento de decisão, sem ativá-las.',
+ 'Response integral/§27 e condições por tipo/unidades, urbanismo/materialidade e entidade sem exercícios ainda parciais. Propostas D-M1–M4/D-S1–S2 requerem decisão; quatro categorias não submetem/publicam até perfil aprovado e adaptador demonstrado.'),
+ 'AUD-PROFILE-22': ('Proposta SLA versionada:triagem2, revisõestécnica/jurídica10 emparalelo, parecer5, correção15, revisão5, editorial3 e recurso2+10 diasúteis; coordenação/responsabilidades e regras de pausa/lembrete/escalamento explícitas.',
+ 'D-SLA:aprovar/rever prazos, calendário/fuso, tolerância e terceirociclo, responsabilidades/suplentes. Nenhuma due_at ou atribuição real alterada; motor/visual do SLA apósdecisão.'),
+ 'AUD-PROFILE-28': ('Propostas inativas concession/financing/supply/other baseadas em§25.4(P2101–2105), reutilizam campos,documentos,geo eworkflow existentes; decisões regra/fundamento/efeito individualizadas.',
+ 'Perfis não aprovados/nem carregadospelo motor; guardar/editar4drafts anterior provado, submissão/revisão/publicação mantidas bloqueadas. Seis contratos completos emUI ainda não demonstrados.'),
+}
+evidence = 'profile-installation-checks-qa.json (testes isolados por critério),profile-installation-http-qa.json,opportunity-office-documents-http-qa.json,geometry-crosswalk-v2-http-qa.json/preservation,readinessQAbackup e dashboard-active-readonly.json; fontes/propostas-perfis-modulares-sla.md. Sem visual/sem escrita ativa.'
+for row in rows:
+ if row['ID'] in entries:
+ implementation, gap = entries[row['ID']]
+ append(row, 'Implementação encontrada', implementation)
+ append(row, 'Lacuna', gap)
+ append(row, 'Evidência funcional', evidence)
+ append(row, 'API', 'HTTP18097/MFA e alvoQA guardado; ver recibo específico. TestesHTTP de feature eminvestmoz_test separados do servidor usado.')
+ append(row, 'Gravação', 'Migração/ledger/auditoria atómicosPG no ensaio isolado; servidor já040usado:noopsemDDL. Recursos/originais e15geometrias gravados somenteQA.')
+ append(row, 'Recuperação', 'Instalador/âmbito eDOCX/XLSX recuperados noutra sessãoFortify/MFA; geometrias porendpoint do componente. SQLrestauro comparado por tabela e ficheiros porhash, com lacunas declaradas na prova.')
+ append(row, 'Interface', 'Código ecompilaçãoQA preparados; nenhum clique/render observado. C37/PromotorQA21/A-B permanecempendentes.')
+ append(row, 'Resultado apresentado', 'JSON/HTMLInertia ebinários demonstrados; apresentação visual não demonstrada.')
+ append(row, 'Disponibilidade ativa', 'AtivoREADONLY:030/040/09-190ausentes,0geometrias,flagsfalse/manifestopreservado; não ativado.')
+ append(row, 'Consolidação', 'Pedido10/10/2026:040autenticado,188correspondênciasbaseline,propostasmodulares/SLA epublicaçãointerna. Estado atual deste incremento prevalece sobre relatos anteriores conservados.')
+document_entries = {
+ 'AUD-LAND-01': ('PDF, PNG e JPEG sintéticos: upload pelo servidor QA, scan ClamD real, original recuperado pelo autor QA21 noutra sessão MFA. Gestor QA14 e outro investidor QA23 recebem 404 no percurso privado. País MZ e origem PT persistidos e recuperados. Modelo de impressão responde com aviso de ausência de decisão externa.',
+ 'Aspeto da interface e PDF gerado pelo navegador pendentes; não demonstra todos os perfis, filtros, estatísticas ou todos os campos fundiários.'),
+ 'AUD-PART-01': ('Sala QA1: PDF, PNG e JPEG privados do autor; candidato recebe 404 e não pode alterar partilha (403). Partilha explícita permite recuperar bytes noutra sessão MFA; revogação retira listagem e download (404), mantendo original do autor. Gestor não participante e organização alheia recebem 403; seis transições de partilha auditadas.',
+ 'Resultado visual, impressão/exportações e restantes ações da bolsa continuam com critérios próprios pendentes.'),
+ 'AUD-SCAN-01': ('Seis originais fundiários/parceria possuem scan real ClamAV limpo, data de assinaturas e hash analisado igual ao original armazenado e recuperado por HTTP. Não foram alterados originais nem simulados scans.',
+ 'ClamD real demonstrado nestas operações; arranque operacional, PDFs gerados, novos tipos e derivadas não cobertos continuam pendentes por operação.')
+}
+for row in rows:
+ if row['ID'] in document_entries:
+ implementation, gap = document_entries[row['ID']]
+ append(row, 'Implementação encontrada', implementation)
+ append(row, 'Lacuna', gap)
+ append(row, 'Evidência funcional', 'independent-documents-http-qa.json e independent-documents-verification-qa.json; servidor QA 18097, API/persistência demonstradas, interface não observada.')
+ append(row, 'API', 'Rotas reais de terra-duat e parcerias/salas; sessões Fortify, verificações permitidas/negadas e cabeçalho do alvo QA antes de escrever.')
+ append(row, 'Gravação', 'Três originais por consumidor e eventos de partilha persistidos exclusivamente na base QA isolada.')
+ append(row, 'Recuperação', 'Nova sessão MFA recupera os mesmos hashes; revogação mantém os originais e remove o acesso do candidato.')
+ append(row, 'Interface', 'Modelo Inertia de impressão recuperado; nenhum clique, mapa ou PDF de navegador observado.')
+ append(row, 'Resultado apresentado', 'JSON, modelo de impressão e binários demonstrados; resultado visual pendente.')
+ append(row, 'Disponibilidade ativa', 'Este ensaio é exclusivamente QA; não inspecionou nem alterou documentos ou partilhas ativos.')
+assert before == [{k: r[k] for k in protected} for r in rows]
+assert len(rows) == 3386 and sum(int(r['Quantidade de linhas de origem']) for r in rows) == 6838
+with matrix.open('w', encoding='utf-8-sig', newline='') as f:
+ w = csv.DictWriter(f, fieldnames=list(rows[0])); w.writeheader(); w.writerows(rows)
+
+marker = 'qa-installation-cartography-20261010'
+def prepend(path, block):
+ old = path.read_text(encoding='utf-8-sig')
+ old = re.sub(r'.*?\s*', '', old, flags=re.S)
+ old = old.replace('Este bloco é a evidência mais recente desta matriz;', 'Este bloco conserva a revisão semântica anterior; o estado atual está no início do documento;')
+ first, _, rest = old.partition('\n')
+ path.write_text(first + '\n\n\n' + readable(block.strip()) + '\n\n\n' + rest.lstrip(), encoding='utf-8')
+
+files_ready = 'todos os ficheiros referenciados recuperados por hash' if backup['files_verified'] else f"{len(backup['missing_document_files'])} ficheiros referenciados ausentes; readiness bloqueada até esclarecer/restaurar"
+summary = f'''## Estado atual — instalador, documentos e cartografia
+
+QA exclusivamente: **http://127.0.0.1:18097**, `desk_restore_20261009_174726_test:55441`. Ativo inspecionado apenas por leitura em {active['captured_at']}: 030000, 040000 e 09/190000 ausentes; zero geometrias; manifesto preservado. **C37, Promotor QA21 e A/B permanecem visualmente pendentes. Candidata à ativação ainda não fixada.**
+
+| Requisitos | Código preparado / prova QA | Critério ainda aberto |
+| --- | --- | --- |
+| PROFILE-31 / OPS-01 | GET/POST `/management/profile-install`, bootstrap separado; prévia, dependências, hash, MFA, repetição e auditoria. Instalação vazia revertida/reinstalada; falha de auditoria reverte DDL e ledger, permitindo repetir. Uso/histórico impedem remoção. No servidor já utilizado, `changed=false`; nenhum titular ou privilégio alterado. Promotor, Auditor e organização alheia recebem 403. | Instalação/bootstrap visual e titulares reais designados; recuperação simultânea da dupla depende de D-R1. Backup do schema não recupera MFA perdido. |
+| GEO-02/03 | **15 novas**: cinco distritos e dez postos; **393 reutilizadas**. Total **408**: 11 províncias, 133 distritos e 264 postos. API do mapa recupera os 15 novos limites. 1.990 cadastros e 361 geometrias originais preservados; sem publicação. | **173 lacunas nomeadas**: 26 distritos e 147 postos; ambiguidades e edições distintas. Seletores/mapas por consumidor continuam com aceitação visual pendente. Localidades/parcelas não inferidas. |
+| OP-02 / documental | DOCX/XLSX: pacote válido, scan ClamD real, acesso de QA21/24/25 e QA23 negado; exclusão lógica, restauro e original idêntico noutra sessão MFA. | Renderização de Office, exportações/PDFs derivados e restantes consumidores continuam pendentes por operação. |
+| LAND-01 / PART-01 / SCAN-01 | PDF, PNG e JPEG em fundiário e sala de parceria: seis scans reais com hashes iguais. Autor recupera originais; partilha explícita permite nova sessão; revogação retira acesso/listagem, sem apagar original. Gestor não ganha acesso por esse papel. **{len(independent['events'])} pedidos** no recibo próprio. | Modelo de impressão recuperado, mas PDF gerado no navegador e interface não demonstrados. Estes seis scans não encerram outros tipos, derivadas ou permissões. |
+| OP-03 / OP-04 | Código da interface e resposta distinguem aprovação interna, disponibilização restrita e catálogo público. Casos #30 restrito, #33 público e #32 aprovado sem publicação recuperados pela API; consulta da política pública efetiva. | Interface; Response integral/§27 e condições sem regra inequívoca continuam parciais. Testes dos seis contratos não encerram a demonstração visual. |
+| PROFILE-22/28 | [Quatro perfis e SLA com regra, fundamento, efeito e decisões concretas](propostas-perfis-modulares-sla.md). | Propostas **inativas**; quatro categorias continuam com rascunhos recuperáveis, mas submissão/publicação bloqueadas. Nenhum prazo ou responsável real configurado. |
+
+Prova de recuperação QA: dump consistente → nova base `{backup['restored_target']['database']}:55441` → **{len(backup['tables'])} tabelas com linhas/hashes iguais e {len(backup['files'])} ficheiros fisicamente recuperados por hash**; {files_ready}. Arquivo privado inclui o runtime e a chave QA estável. Readiness só atesta preparação técnica desta revisão. Repetir após fixar a candidata e preparar backup ativo apenas numa futura ativação autorizada.
+
+**Matriz única:** 3.386 requisitos/linhas e 6.838 ocorrências de origem; todas as fontes, critérios e versões preservados; sem novos fechos globais. Contagens por estado abaixo e na projeção dos pedidos abertos.
+
+**Próximo lote executável:** completar Response/§27 reutilizando entidades; verificar exportações e PDFs derivados por consumidor; prosseguir correspondências territoriais por nome, pai e edição; completar países/origem, filtros e estatísticas por formulário. Incorporar provas visuais quando retomadas. Decisões D-M1–M4, D-S1/S2, D-SLA e D-R1 estão individualizadas e não bloqueiam o trabalho independente.
+
+**Histórico preservado:** os blocos seguintes descrevem revisões anteriores. 393 geometrias/188 lacunas eram o estado antes deste lote; “instalador 040000 em falta” deixou de descrever o código QA. Esses estados anteriores não provam esta revisão nem autorizam instalação ativa.
+'''
+prepend(DOCS / 'relatorio-executivo.md', summary)
+prepend(DOCS / 'backlog.md', summary)
+prepend(DOCS / 'workflow-oportunidades-qa.md', summary)
+prepend(ROOT / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', summary.replace('(propostas-perfis-modulares-sla.md)', '(auditoria-portal/propostas-perfis-modulares-sla.md)'))
+
+activation = '''## Sequência reconciliada — preparada, não executada no ativo
+
+**030000 → 040000 → 190000** mantém-se. QA já tem as três; **não repetir instalações QA**. No ativo lido READ ONLY, as três extensões estão ausentes; Balcão07/190000 eorientação08/120000 estão instalados. A extensão **09/190000 não foi substituída**: faltam ledger,duascolunas e definição19etapas. Fonte:dashboard-active-readonly.json eopportunity-semantic-environment-qa.json.
+
+| Ordem | Ação futura, efeito econtagem prevista | Dependência / reversão |
+| --- | --- | --- |
+| 0 | VisualC37/QA21/A-B ecorreções→fixar candidata/hash/manifesta/config→backupDB+originais+runtime/chaveestável→restauro emQA nova, tabelas/bytes/acessos comparados. | QA backup deste lote não é backup ativo nem candidata definitiva. Ativação continua fora da autorização. |
+| 1 | Disponibilizar código/Composer/build compatíveis, flagsfalse eURLs preservadas. | Não retirar privilégios reais ou migraridentidades automaticamente. Reverter flags/build/código compatível preservando dados novos. |
+| 2 —030 | GETprévia→POST `/management/opportunity-resources-install`, hash/confirm/MFA/provas atuais, sóse ausente/coerente. **3coleções+metadado cifra;0documentos importados/publicados.** | Base020/documentos existentes. Não drop apósuso; restaurar/reconciliar backup em vez de apagar originais. |
+| 3 —040 | GETprévia→POST `/management/profile-install`; **4tabelas+1colunausers+3colunasoportunidades,0contas/grants/flags.** BootstrapPOST `/management/profile-install/bootstrap` é **separado**:2contas explicitamente designadas,3.ºgestor comMFAaprova. | Instalador exige020+030/schema/organização/auditoria, hash ebackup/restauro atuais. Idempotência eDDL/ledger/auditoria atómicos. Schema parcial bloqueia aplicação; down apenassemqualqueruso/contexto/revisão/histórico. Recuperação deMFA simultânea exigeD-R1,sembootstraprepetido. |
+| 4 —09/190 | GETprévia→POST `/management/balcao-install`, sómigraçãofaltante: **2colunas+1definição publicada19etapas/5fases;0dossiers automáticos.** | BaseBalcão/orientação jáinstaladas: não repetir. SemdepDDLde040,masordem operacional preservada. Template eversões usados imutáveis; reverterdisponibilização,preservar snapshots/roteiros. |
+| 5 —cartografia | GETprévia→POST `/management/territory-geometry-import`, níveis1→2→3 ehash/idempotência. **408 correspondências candidatas** se cadastro/hash coincidem:11/133/264;ativo0na leitura. **173pendentes** não importadas. | Fontes/hash/pai/nome/código vinculados;resultado/contagem medida no alvo,semfusões ougeometrias inventadas. Reversão só lotesnovos nãoalterados/usados,postos→distritos→províncias comaudit;seFK/uso,preservar/reconciliar,nãoforçar. |
+| 6 —disponibilização | Aprovar perfis/reconciliação depermissões reais econfiguração; habilitar navegação/editores/percurso porincremento comprovado. **0fixtures QA noativo.** | I1–I3 não concluídos semA/B/UI. Contratos4categorias eSLA sóapósdecisão própria. Importação não ativa cálculo fiscal. |
+| 7 —publicação | Revisão dedivulgação eação doPublicador porversão; **camadas cartográficas públicas são ação separada** daimportação. | Aprovaçãointerna≠acessorestrito≠catálogopúblico≠decisãoexterna. Desabilitar publicação/flags antes derestauro;preservar originais,consentimentos eauditoria. |
+
+Sharedcode/fingerprint muda:renovar provas da revisão ealvo;ready=true não instala,não escolhe titulares,não publica enão disponibiliza percurso. Guarda ativa/QA conferida antes decada escrita futura. A prova040 emschema vazio foi isolada; no servidorQA jáusado sónoop auditado.
+'''
+prepend(DOCS / 'plano-ativacao.md', activation)
+
+cases = '''## Casos adicionais deste lote — sem reiniciar o inventário
+
+| Caso / requisito | Reprodução e resultado esperado | Observado, causa e correção | Prova / estado |
+| --- | --- | --- | --- |
+| C59 — PROFILE-31 / OPS-01 | Gestor confirmado com MFA consulta e aplica apenas 040000, após030000; repetir o mesmo pedido. Esperado:prévia, dependências e provas, uma instalação e um recibo, sem contas/grants automáticos. | A migração já tinha guarda, mas faltava rota/serviço/interface autenticados. Reutilizados Fortify, audit_events e cerimónia da dupla. Plano obsoleto/chave alterada409; falta de provas/dependência422; Auditor/Promotor403. | Testes de feature em schema vazio, repetição e bootstrap separados; servidor18097 já instalado:noop, replay idêntico, novaMFA e negações. Visual pendente. |
+| C60 — PROFILE-31 / recuperação | Em base isolada e schema vazio, down→instalar; depois impedir insert na auditoria e instalar. Esperado:reversão total deDDL/ledger se não houver recibo; retry possível; nenhum drop com uso/histórico. | No desenvolvimento do incremento foi introduzida remoção duplicada da colunausers; o ensaio encontrou Undefined column. Corrigida. Também reforçado down para contexto/organização sem autor e revisões de sessão; falha de auditoria devolve503 e não deixa schema/ledger parcial. | Testes específicos de reinstalação e falha auditiva; históricos/contextos conservados. Não executado down no servidorQA utilizado, nem no ativo. |
+| C61 — OP-03 / publicação | Recuperar #30,#33,#32 e comparar estado da preparação, âmbito efetivo e catálogo. Esperado:restrito,público,aprovado sem disponibilização respetivamente. | Rótulo genérico “Publicado”/estado published não explicava o âmbito. Novo label/projeção consulta política efetiva do catálogo; botões distinguem disponibilização restrita de publicação pública. | JSON/Inertia e política pública verificados; nenhuma fuga pública observada. Perceção/ação visual pendente. |
+| C62 — PROFILE-31 / bootstrap | Propor duas contas distintas e terceiro gestor; candidato com MFA cifrado ilegível ou Auditor. Esperado:recusa controlada e nenhum titular criado. | A cerimónia conferia presença/confirmaçãoMFA, sem comprovar leitura do segredo no ambiente. Agora exige cifragem válida/estruturaMFA e recusa Auditor, mesmo com flags ainda desabilitadas. Sem key:generate/fallback ou remoção deMFA. | Teste422 e dupla permanece vazia; inicialização positiva com identidades sintéticas distintas. Não substitui C37/login visual. |
+| C63 — ambiente de testes / documental | Executar IndependentDocumentOperationsTest com o PHPCLI padrão. Esperado:GD disponível para gerar as imagens do ensaio. | Dois testes falharam por imagecreatetruecolor inexistente noCLI; o servidorQA já tinhaGD. Runner passa a carregar explicitamente a mesma extensãoGD para o processo de testes. | Regressão posterior27/600 semskips, scans reais e testes finais separados. Não atribuir esta falha ao servidorweb ou declarar GD ativo verificado. |
+| C64 — PROFILE-31 / recuperação e proteção | Em schema isolado com perfis habilitados, retirar a coluna de revisão e tentar desativar MFA/excluir conta. Esperado:sem alteração de identidade, recuperação e logout acessíveis. | Esquema parcial podia tornar o serviço de perfis indisponível e deixar middleware de proteção passar à frente. Agora recusa escritas com503, preserva MFA/conta e deixa o instalador apresentar a incoerência409; logout permanece permitido. | Teste específico, schema parcial não aplicado ao servidorQA nem ao ativo. Preserva leitura permitida e não cria bypass de recuperação. |
+
+C55 continua corrigida por operação:PDF eagoraDOCX/XLSX excluídos dão404, scanpendente continua423; restore preserva original. C37/C43/QA21/A-B permanecempendentes. Cada prova mantém API/persistência/interface separadas.
+'''
+prepend(DOCS / 'casos-reproducao.md', cases)
+manual = f'''## Ensaio visual futuro deste lote — contas QA, sem credenciais
+
+Servidor exclusivo **http://127.0.0.1:18097**. Para a instalação, usar o **Superutilizador sintético QA27** já designado na dupla27/30; obter credenciais eMFA somente no ficheiro privado local. **Promotor QA21 continua a conta do dashboard, não substituí-lo por27. C37/QA18 e A/B continuam pendentes; não é pedida nova tentativa agora.**
+
+1. ComoQA27, login/MFA normal e abrir **http://127.0.0.1:18097/management/profile-install**. Conferir oalvo apresentado `desk_restore_20261009_174726_test:55441`, schema instalado, dependências020/030 presentes, provas atuais e dupla existente. Não executarbootstrap ou escolher titulares novos neste servidor usado.
+2. Atualizar a página, terminar sessão einiciar outra. Esperado:mesmo ledger e dupla,semnova instalação ou atribuição. Os testes de instalação desde schema vazio/reversão pertencem àbaseisolada do runner; não remover o040 do servidorQA emuso para demonstrar o botão.
+3. Quando retomarQA21, dashboard→Minhas oportunidades; #30 apresenta acesso restrito e não catálogo; #33 apresenta catálogo público; #32 apresenta aprovação interna,sempublicação. Os originais/contatos privados não entram na projeção pública.
+4. ComoQA21, abrir **http://127.0.0.1:18097/minhas-oportunidades/36/resources**:consultar PDF,DOCX eXLSX sintéticos. Guardar original, excluir logicamente um recurso, esperar404/downloadindisponível; restaurar einiciar outra sessão para recuperar os mesmosbytes. QA24/25 podemconsultar; organizaçãoQA23 énegada.
+5. Selecione CahoraBassa/Chitima ouCidadeMaxixe no consumidor territorial. Esperado:mesmoIDexistente, geometria administrativa comedição2019, legenda eárea selecionada. Guardar/recuperar seleção; não confundir limite administrativo comparceladeinvestimento. Inspecionar cadaoutroconsumidor no roteiroexistente.
+6. Registar URL,conta/ação/resultado visível eestado recuperado. Omitir Cookie,X-XSRF-TOKEN,password,segredo/códigoMFA. Incorporar falhasàmesma matriz antes defixar candidata.
+
+Documentos fundiários QA21: **http://127.0.0.1:18097/investidor/terra-duat/{independent['receipts']['case_id']}**. Conferir PDF/PNG/JPEG e país MZ/origem PT; abrir impressão e gerar PDF no navegador. A recuperação do modelo por HTTP não demonstra o PDF final.
+
+Partilha QA21/22: **http://127.0.0.1:18097/parcerias/salas/{independent['receipts']['room_id']}**. Os três originais estão privados após o ensaio. QA21 partilha explicitamente um; QA22 recupera noutra sessão. QA21 revoga; QA22 deixa de o listar/obter; QA21 mantém o original. QA14 não participante e QA23 não têm acesso à sala.
+
+Este roteiro não declara os passos executados. Instalação ativa e publicação de camadas permanecem ações futuras separadas.
+'''
+prepend(DOCS / 'roteiro-manual-perfis-v1.md', manual)
+prepend(DOCS / 'perfis-v1-reconciliacao.md', summary)
+
+cartography = '''## Correspondências atuais — v2
+
+Esperado refere o exemplar aceite INE/UNOCHA07/06/2019, não uma certificação da divisão atual. Fonte oficial continua aceite. Nome/pai/edição são problemas de correspondência, não revalidação da credibilidade.
+
+| Nível | Esperado | Resolvido QA | Pendente | Incremento deste lote |
+| --- | ---: | ---: | ---: | ---: |
+| Províncias |11|11|0|0|
+| Distritos |159|133|26|5|
+| Postos administrativos |411|264|147|10|
+| Total |581|408|173|15|
+
+Baseline anterior393/188 mantida nohistórico. As antigas2/39/179 eram a situação09/10; não descrevem oestadoatual. Cadastro do seletor1920referências (11+148+437+1324),mais70países;geometria eapresentação funcional têm denominadores próprios. Semgeometriasdelocalidades/parcelas desteexemplar.
+
+Cinco aliasesdedistritos: **Cahora Bassa→CAHORA-BASSA;Ngauma→N`GAUMA;Ilha De Moçambique→CIDADE ILHA DE MOCAMBIQUE;Maxixe→CIDADE DE MAXIXE;Nacala-A-Velha→NACALA-VELHA**. Postos exatos pelospais:Chitima,Covo,Ilha De Moçambique,Itepela,Lumbo,Massangulo,Songo;aliasesapóstrofo:M'Sawize→M`SAWIZE,N'Cumpe→NCUMPE,N'Gapa→N`GAPA. Fonte,código,pai ecadastro existentes conferidos pela prévia;fundamento ehash emconfig/geometry-correspondences.phpv2 eprovaHTTP. Semrenomeação oualteraçãohierárquica.
+
+geometry-crosswalk-v2-http-qa.json:15inserts/393reuse,replayigual e15limites recuperadospelaAPI domapa;sempublicação/semvisual. geometry-crosswalk-v2-preservation-qa.json:1990cadastros/361originaispreservados e47incrementaisprivados. Reversão existente não apaga originais;atualizaçãousada recusada. Mandie continua ambíguo entre2cadastros/códigos sobGuro;CidadeDeMaputoagregado nãoequivalea1distritourbano. Novosdistritos/edições nãoassociadosporproximidade.
+'''
+for level in [2, 3]:
+ items = [g for g in gaps if g['level'] == level]
+ cartography += f"\n### {'Distritos' if level == 2 else 'Postos'} — {len(items)} lacunas por nome\n\n| Código | Nome | Província / pai | Causa |\n| --- | --- | --- | --- |\n"
+ for g in items:
+ cartography += f"|{g['pcode']}|{g['name']}|{g['province']} / {g['parent_name']}|{g['reason']}|\n"
+cartography += '\n**Visual pendente:**cada seletor/país/origem/mapa porformulário, gravação erecuperação;408 APIs não demonstram render. Todasasfontes,nomes econtagensanteriores seguemabaixo como história.\n'
+prepend(DOCS / 'correspondencias-cartograficas.md', cartography)
+
+states = collections.Counter(r['Estado'] for r in rows)
+state_text = '## Contagens atuais por requisito\n\n| Estado | Requisitos / linhas da matriz | Ocorrências de origem |\n| --- | ---: | ---: |\n'
+for state, count in states.items():
+ state_text += f"|{state}|{count}|{sum(int(r['Quantidade de linhas de origem']) for r in rows if r['Estado'] == state)}|\n"
+state_text += '\n3.386 requisitos verificáveis e 3.386 linhas consolidadas; 6.838 ocorrências de origem. Sem novo fecho integral; provas QA descritas por critério.\n'
+for name in ['relatorio-executivo.md', 'backlog.md']:
+ path = DOCS / name
+ text = path.read_text(encoding='utf-8-sig').replace('', state_text + '', 1)
+ path.write_text(text, encoding='utf-8')
+counts_path = PRIVATE / 'contagens-requisitos.json'
+counts = json.loads(counts_path.read_text(encoding='utf-8-sig'))
+counts.update({'installation_updated_at': datetime.now(timezone.utc).isoformat(), 'requisitos': len(rows), 'linhas_matriz': len(rows),
+ 'linhas_origem': 6838, 'por_estado': {s: {'requisitos': n, 'linhas_origem': sum(int(r['Quantidade de linhas de origem']) for r in rows if r['Estado'] == s)} for s, n in states.items()},
+ 'browser_current_version_verified': False})
+counts_path.write_text(json.dumps(counts, ensure_ascii=False, indent=2), encoding='utf-8')
+
+inventory = DOCS / 'inventario-fontes.csv'
+inv = list(csv.DictReader(inventory.open(encoding='utf-8-sig', newline='')))
+proposal = DOCS / 'propostas-perfis-modulares-sla.md'
+name = str(proposal)
+entry = next((r for r in inv if r['Exemplar/caminho'] == name), None)
+if entry is None:
+ entry = {k: '' for k in inv[0]}; entry['Exemplar/caminho'] = name; inv.append(entry)
+entry.update({'Bytes': str(proposal.stat().st_size), 'SHA256': hashlib.sha256(proposal.read_bytes()).hexdigest(), 'Tipo': 'proposta interna QA',
+ 'Nota de leitura': 'Documento integral; regras/fundamento/efeito/decisões efonte§25.4. Não fonteoficial,nenhuma aprovaçãoinferida.',
+ 'Disponibilidade': 'Consulta no repositório; publicação não inferida', 'Uso em cálculo': 'Nenhuma regra/SLA/cálculo ativado',
+ 'Situação jurídica/documental': 'Proposta para decisão, não ato jurídico', 'Edição/versão identificada': 'proposta20261010v1'})
+with inventory.open('w', encoding='utf-8-sig', newline='') as f:
+ w = csv.DictWriter(f, fieldnames=list(inv[0])); w.writeheader(); w.writerows(inv)
+(PRIVATE / 'installation-audit-update-qa.json').write_text(json.dumps({'updated_at': datetime.now(timezone.utc).isoformat(), 'requirements': 3386,
+ 'source_occurrences': 6838, 'protected_fields_preserved': True, 'states': dict(states), 'updated': list(entries), 'geometry_total': 408,
+ 'document_originals_verified': 6, 'document_requirements_updated': list(document_entries), 'named_pending': 173, 'active_writes': 0}, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'requirements': 3386, 'source_occurrences': 6838, 'updated': list(entries) + list(document_entries), 'geometries': 408, 'pending': 173, 'active_writes': 0}))
diff --git a/tools/portal-audit-open-requests.py b/tools/portal-audit-open-requests.py
new file mode 100644
index 00000000..91f66a04
--- /dev/null
+++ b/tools/portal-audit-open-requests.py
@@ -0,0 +1,104 @@
+"""A read-only, searchable view of every open requirement in the existing CSV."""
+import collections
+import csv
+import hashlib
+import html
+import json
+import sys
+from pathlib import Path
+
+sys.stdout.reconfigure(encoding='utf-8')
+csv.field_size_limit(16 * 1024 * 1024)
+root = Path(__file__).resolve().parent.parent
+docs = root / 'docs/investmoz/v2/auditoria-portal'
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+matrix = docs / 'matriz-requisitos.csv'
+rows = list(csv.DictReader(matrix.open(encoding='utf-8-sig', newline='')))
+opened = [r for r in rows if r['Estado'] != 'concluído e demonstrado']
+prepared = {'AUD-COUNTRY-01', 'AUD-COUNTRY-02', 'AUD-COUNTRY-03', 'AUD-COUNTRY-04', 'AUD-COUNTRY-06', 'AUD-COUNTRY-07', 'AUD-STATS-01',
+ 'AUD-GEO-01', 'AUD-OP-01', 'AUD-OP-02', 'AUD-OP-05', 'AUD-DESK-01', 'AUD-DESK-02', 'AUD-CRM-01', 'AUD-GUIDE-01', 'AUD-SIM-01', 'AUD-PART-01', 'AUD-LAND-01', 'AUD-LIB-02'}
+access_failure = {'AUD-DASH-01', 'AUD-UI-01'}
+prepared.update({'AUD-OP-03','AUD-OP-04','AUD-PROFILE-19'})
+prepared.update(f'AUD-PROFILE-{number:02d}' for number in [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,23,24,25,30,31,32])
+groups = ['Não implementados', 'Parciais', 'Preparados em QA', 'Instalados com falha de acesso']
+
+
+def group(row):
+ if row['Estado'] == 'não implementado':
+ return groups[0]
+ if row['ID'] in access_failure:
+ return groups[3]
+ if row['ID'] in prepared or row['Estado'] == 'implementado mas não ativado':
+ return groups[2]
+ return groups[1]
+
+
+next_actions = {
+ 'AUD-DASH-01': 'Identificar URL/conta da sessão reportada; no servidorQA, gestor17: dashboard→Gestão de Oportunidades→Nova oportunidade→guardar→nova sessão→editar→arquivar→restaurar. Incorporar prova visualC43 antes de futura disponibilização dos atalhos.',
+ 'AUD-UI-01': 'ManterC37 pendente; executar separadamente login/reload/logout/nova sessão investidor18 e os cenáriosA/B completos, depois as demais rotas/consumidores. Sem novo pedido de autorizaçãoQA.',
+ 'AUD-OP-01': 'Executar roteiro visualC43 a partir do dashboard com gestorQA17/MFA; conferir mensagens, filtro archived,ID/histórico e público intacto.',
+ 'AUD-OP-02': 'Conferir operações visuais por tipo/perfil e scans próprios de derivadas; após aceitação/backuprestaurado, aplicar autenticadamente030000 apenas se ausente. Não repetir020000.',
+ 'AUD-OP-03': 'Executar ciclo visual com PromotorQA21, Validador24, Publicador25 e recurso29; API/persistência do ciclo já demonstradas. Completar pareceres/incidentes/coordenação editorial e política SLA/agenda sem inventar responsáveis ou prazo.',
+ 'AUD-OP-04': 'Completar editores/validações semânticas §25 e Response integral; seis contratos estruturais aceites em QA não encerram todos os gates. Quatro categorias conservam drafts, mas exigem perfil modular aprovado para submissão/publicação.',
+ 'AUD-OP-05': 'Selecionar/guardar/reabrir7/8 na interface com versão do catálogo explícita; conferir legado6sem converter significados e fases de revisão/publicação.',
+ 'AUD-GEO-01': 'Pesquisar cada província, guardar/reabrirID/nome e confirmar o limite no seletor partilhado para cada perfil.',
+ 'AUD-GEO-02': 'Resolver188nomes(31distritos/157postos) por pai+edição/correspondência inequívoca; aplicar privadamenteQA, replaysem duplicação; percorrer cada seletor e limpar filhos ao mudar pai.',
+ 'AUD-GEO-03': 'Verificar mapa por consumidor com393limites privados e permissões; distinguir referência/limite/perímetro; resolver31/157e disponibilidade de polígonos de localidades. Publicação separada.',
+ 'AUD-REL-01': 'Ligar as relações existentes a citações e fonte/edição específicas; não inferir pares oportunidade–projeto/cluster nem criar ligações sem evidência.',
+ 'AUD-REL-02': 'Pergunta concreta:quais são os pares identificados e documentados entre as seis oportunidades existentes e âncoras/clusters? Preservar relações atuais enquanto indeterminados.',
+ 'AUD-SIM-02': 'Completar correspondência diploma/artigo/âmbito/período/parâmetro nas fontes oficiais aceites; testar cenários rastreáveis. Taxa ausente permanece indeterminada; importação não ativa cálculo.',
+ 'AUD-LIB-01': 'Completar consulta do acervo/autorização por ficheiro a partir do inventário253ficheiros+60anexos; preservar original/hash/versão e estados consulta,jurídico e cálculo independentes.',
+ 'AUD-LIB-02': 'Completar aplicação por mecanismo autenticado, prévia/hash/duplicação/conflito/escrita privada/scan; CLIapply continuaQA-only. Conferir partilha/revogação/tipos na interface.',
+ 'AUD-SCAN-01': 'Verificar scan próprio de cada operação/derivada restante e arranque/reboot/assinaturas ClamD/GD no servidor de futura ativação; provaClamD real existente mantida.',
+ 'AUD-DESK-01': 'Percorrer os três serviços e seus anexos/estados por perfil; guardar/reabrir campos/país/origem e mostrar resultado/pendências/recibo.',
+ 'AUD-DESK-02': 'CenáriosA/B:abrir Balcão com o dossier correto→preparar apoio→recuperar pedido/acompanhamento noutra sessão, sem misturar projetos.',
+ 'AUD-CRM-01': 'Preparar apoioA/B e acompanhar com responsável/próxima ação interna; verificar permissões/nova sessão e atualização visível, semCRMexterno como dependência.',
+ 'AUD-GUIDE-01': 'Conferir cada recomendação contra âmbito/período/elementos da fonte oficial aceite; exibir fundamento/próxima ação sem score de aprovação inventado.',
+ 'AUD-SIM-01': 'Abrir ferramenta a partir do dossierA/B→guardar cenário→devolver/recuperar resultado no mesmo dossier noutra sessão; verificar isolamento e acesso direto.',
+ 'AUD-PART-01': 'Completar rascunho/candidatura/sala/marcos por perfis, partilha/revogação e downloads/renderização na interface, preservando originais e consentimentos.',
+ 'AUD-LAND-01': 'Percorrer formulário fundiário/país/origem/localização/anexo/partilha com gravação e nova sessão; vincular direitos existentes sem venda automática deDUAT.',
+ 'AUD-BIZ-01': 'Completar negócio existente com direitos/mandatos/documentos e geografia/país, revisar/publicar por ação própria e confirmar recuperação/perfis na interface.',
+ 'AUD-EDU-01': 'Retomar somente após as falhas prioritárias:reutilizar atores/cadastros e demonstrar procura/capacidade/investimento com dados reais e permissões.',
+ 'AUD-EDU-02': 'Depois deI0/C43/contratos prioritários, permitir guardar procura/capacidade incompletas como rascunho privado nas entidades existentes, sem exigir os campos finais.',
+ 'AUD-EDU-03': 'Não iniciar agora; depois das prioridades, jornadas/painéis por ator reutilizando19etapas/5fases e contas existentes, sem renumerar roteiros.',
+ 'AUD-OPS-01': 'Concluir critérios visuais→fixar candidata→renovar backup/restauro→disponibilizar código/flags→instalar somente migrations ausentes→percurso/importação/publicação separadas, com reversão preservadora.',
+ 'AUD-DOC-01': 'Reconciliar individualmente cláusulas/versões com prova datada; conservar os estados históricos e atualizar somente o critério demonstrado na matriz única.',
+ 'AUD-UX-01': 'Percorrer interface/teclado/móvel e remover somente informação sem utilidade demonstrada, preservandoIDs/URLs e rastreabilidade.',
+ 'AUD-HUMAN-01': 'Pergunta concreta:qual é a entidade operadora, contacto oficial e texto/versão dos termos a apresentar? Não atribuir a entidade/responsável inexistente.',
+ 'AUD-HUMAN-02': 'Pergunta concreta:quais URLs, serviços e responsáveis institucionais devem ser associados? Percursos internos continuam independentes destas integrações.',
+ 'AUD-HUMAN-03': 'Pergunta concreta:qual modelo multicritério, indicadores ebaseline/pilotos estão aprovados? Até haver definição, apresentar evidências/cenários sem score de sucesso.'}
+for id in ['AUD-COUNTRY-01', 'AUD-COUNTRY-02', 'AUD-COUNTRY-03', 'AUD-COUNTRY-04', 'AUD-COUNTRY-06', 'AUD-COUNTRY-07', 'AUD-STATS-01']:
+ next_actions[id] = 'Na cobertura existente, testar o formulário específico→país/origem→guardar→nova sessão→recuperar→filtro→estatística correspondente. API já provada não encerra a interface; residência/fiscal/fundos não substituem origem declarada.'
+
+
+def action(row):
+ if row['ID'].startswith('AUD-PROFILE-'):
+ return row['Lacuna'] + ' Ver plano e roteiro em perfis-v1-reconciliacao.md; continuar QA sem afetar ativo.'
+ if row['ID'] in next_actions:
+ return next_actions[row['ID']]
+ if row['ID'].startswith('AUD-FIELD-'):
+ return 'Executar neste consumidor específico:pesquisar→selecionar→guardar→reabrir→apresentar no campo/mapa; trocar pai→limpar filhos; verificar autorização. Corrigir falha reproduzida usando os componentes territoriais existentes.'
+ return 'Conferir e completar emQA o critério específico abaixo nas rotas/entidades existentes, preservandoIDs e versões; registar interface/API/gravação/recuperação/resultados separados. Correspondência ainda não provada exige localizar a implementação antes de atribuir conclusão.'
+
+
+escape = html.escape
+counts = collections.Counter(group(r) for r in opened)
+cards = []
+for r in sorted(opened, key=lambda x: (groups.index(group(x)), x['Prioridade'], x['Módulo'], x['ID'])):
+ body = ''.join('' + escape(label) + ' ' + escape(r[key]) + ' ' for label, key in [('Pedido', 'Pedido/trecho'), ('O que falta', 'Lacuna'), ('Rotas', 'Rotas'), ('Componentes encontrados', 'Implementação encontrada')])
+ cards.append(''+escape(r['ID'])+' · '+escape(r['Módulo'])+' '+escape(group(r))+' · '+escape(r['Estado'])+' · '+escape(r['Prioridade'])+'
'+body+'Próxima ação '+escape(action(r))+' Critério de aceitação '+escape(r['Critério de aceitação'])+' Fontes, versões e evidência do requisito '+''.join(''+escape(k)+' '+escape(r[k])+' ' for k in ['Fonte/ocorrências', 'IDs das linhas de origem', 'Quantidade de linhas de origem', 'Versões divergentes', 'Critérios e versões por origem (JSON)', 'Disponibilidade ativa', 'Evidência funcional', 'Interface', 'API', 'Gravação', 'Recuperação', 'Resultado apresentado'])+' ')
+summary = '; '.join(g+': '+str(counts[g]) for g in groups)
+page = '''InvestMoz — pedidos abertos Pedidos anteriores ainda abertos Vista de leitura gerada exclusivamente da matriz-requisitos.csv. Não é outra matriz nem permite editar estados. 3.354 requisitos/linhas;5.830 ocorrências;5 concluídos de âmbito restrito;3.349 abertos.
''' + escape(summary) + '''
O agrupamento indica a frente de trabalho; mantém o estado canónico em cada cartão. “Preparados em QA” identifica provas de escopos concretos e conserva as lacunas do requisito inteiro. “Instalados com falha de acesso” reúneC43/C37 ainda abertos, com correções/backendQA e aceitação visual pendente; não confirma o perfil da sessão reportada. As4decisões concretas permanecem emParciais com o seu estado original.
''' + ''.join(cards) + ''' '''
+page = page.replace('3.354 requisitos/linhas;5.830 ocorrências;5 concluídos de âmbito restrito;3.349 abertos.',
+ f'{len(rows):,} requisitos/linhas;{sum(int(r["Quantidade de linhas de origem"]) for r in rows):,} ocorrências;{len(rows)-len(opened)} concluídos de âmbito restrito;{len(opened):,} abertos.')
+page = page.replace('3.349 requisitos apresentados', f'{len(opened):,} requisitos apresentados')
+decision_count = sum(r['Estado'] == 'dependente de decisão concreta' for r in opened)
+page = page.replace('As4decisões concretas', f'As{decision_count}decisões concretas')
+(private / 'pedidos-abertos.html').write_text(page, encoding='utf-8')
+proof = {'matrix_sha256': hashlib.sha256(matrix.read_bytes()).hexdigest(), 'canonical_requirements': len(rows), 'source_occurrences': sum(int(r['Quantidade de linhas de origem']) for r in rows),
+ 'open_requirements': len(opened), 'group_counts': dict(counts), 'decision_requirements': [r['ID'] for r in opened if r['Estado'] == 'dependente de decisão concreta'],
+ 'open_ids': [r['ID'] for r in opened], 'one_card_per_open_id': len(cards) == len(opened) == len({r['ID'] for r in opened}),
+ 'report_sha256': hashlib.sha256(page.encode()).hexdigest(), 'qa_authenticated_url': 'http://127.0.0.1:18097/qa-auditoria/pedidos-abertos'}
+assert proof['one_card_per_open_id'] and sum(counts.values()) == len(opened)
+(private / 'pedidos-abertos-projection.json').write_text(json.dumps(proof, indent=2, ensure_ascii=False), encoding='utf-8')
+print(json.dumps({k: v for k, v in proof.items() if k != 'open_ids'}, ensure_ascii=False))
diff --git a/tools/portal-audit-profiles-docs.py b/tools/portal-audit-profiles-docs.py
new file mode 100644
index 00000000..4f12ea22
--- /dev/null
+++ b/tools/portal-audit-profiles-docs.py
@@ -0,0 +1,222 @@
+"""Current executive evidence and readable projections of the sole requirement matrix."""
+import csv
+import json
+import re
+import sys
+import xml.etree.ElementTree as ET
+from pathlib import Path
+
+sys.stdout.reconfigure(encoding='utf-8')
+csv.field_size_limit(16 * 1024 * 1024)
+ROOT = Path(__file__).resolve().parent.parent
+DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+counts = json.loads((PRIVATE / 'contagens-requisitos.json').read_text(encoding='utf-8'))
+projection = json.loads((PRIVATE / 'pedidos-abertos-projection.json').read_text(encoding='utf-8'))
+current = json.loads((PRIVATE / 'profiles-v1-current-version-qa.json').read_text(encoding='utf-8'))
+preservation = json.loads((PRIVATE / 'profiles-v1-preservation-qa.json').read_text(encoding='utf-8'))
+rows = list(csv.DictReader((DOCS / 'matriz-requisitos.csv').open(encoding='utf-8-sig')))
+profiles = [r for r in rows if r['ID'].startswith('AUD-PROFILE-')]
+test_suite = ET.parse(PRIVATE / 'profiles-v1-final-qa.xml').getroot().find('testsuite')
+assert test_suite is not None and test_suite.get('failures') == '0' and test_suite.get('errors') == '0'
+assert len(profiles) == 32 and current['browser_visual_observed'] is False
+
+def update(name, body):
+ path = DOCS / name
+ text = path.read_text(encoding='utf-8-sig')
+ start, end = '', ''
+ block = start + '\n' + body.strip() + '\n\n' + end
+ if start in text:
+ text = re.sub(re.escape(start) + '.*?' + re.escape(end), lambda _: block, text, flags=re.S)
+ else:
+ heading, rest = text.split('\n', 1)
+ text = heading + '\n\n' + block + '\n\n> Registos anteriores preservados como histórico. Os estados correntes são os da matriz e do bloco mais recente acima; uma entrega posterior não altera retroativamente a evidência anterior.\n' + rest
+ path.write_text(text, encoding='utf-8')
+
+status_table = '\n'.join(f"| {name} | {data['requisitos']} | {data['linhas_origem']} |" for name,data in counts['por_estado'].items())
+groups_table = '\n'.join(f'| {name} | {total} |' for name,total in projection['group_counts'].items())
+details = '\n\n'.join(f"**{r['ID']} — {r['Pedido/trecho']}** ({r['Estado']}).\n\nImplementação: {r['Implementação encontrada']}\n\nProva: {r['API']}\n\nLacuna/próxima ação: {r['Lacuna']}\n\nAceitação: {r['Critério de aceitação']}" for r in profiles)
+
+clean_executive = f"""## Perfis v1: resultado do lote em QA — 10/10/2026
+
+A v1 foi lida integralmente: 530 parágrafos, confrontados com os 471 do exemplar anterior, AGENTS, auditoria, código, schema PostgreSQL e configuração. Fortify, contas, documentos, relações, IDs, classificações, histórico, cinco fases e 19 etapas foram preservados. Keycloak foi avaliado como recomendação; não há necessidade de SSO/federação demonstrada para substituir Fortify neste lote. A aceitação das fontes oficiais permanece intacta.
+
+**A mesma matriz contém 3.386 requisitos/linhas e 6.838 ocorrências de origem.** Os 3.354 requisitos e 5.830 referências anteriores foram conservados. Acrescentaram-se 32 requisitos verificáveis, os 1.001 parágrafos dos dois exemplares e sete referências diretas da reconciliação. Parágrafos de estrutura e tabelas são referências, não pedidos independentes. Inventário: 591 exemplares, versões e anexos; 202 ficheiros acessíveis nesta varredura, incluindo 12 marcadores de bloqueio Office preservados por bytes/hash.
+
+| Estado canónico | Requisitos | Ocorrências |
+| --- | ---: | ---: |
+{status_table}
+
+O sexto concluído é apenas **AUD-PROFILE-27**, a avaliação arquitetural de Keycloak. Não encerra autenticação visual nem uma integração externa. **AUD-OP-03 passa a parcial**, pelas regras e transições novas; o workflow integral continua aberto.
+
+QA: **http://127.0.0.1:18097**, destino efetivamente verificado `desk_restore_20261009_174726_test:55441`, com guarda antes de escrita. Foram preparadas 12 contas sintéticas, com MFA configurado e confirmado normalmente por Fortify, duas organizações e quatro representações. O ensaio comprovou:
+
+- Dashboard do Promotor → links devolvidos pela interface → criação do rascunho 15 → gravação idempotente → nova sessão MFA → recuperação → edição pelo outro Promotor autorizado da mesma organização. Autor e ID permanecem; outra organização, tipo não autorizado e transferência de organização recebem 403.
+- Quatro pedidos de Promotor, comprovativos privados com ClamD real e hash recuperado, acompanhamento noutra sessão e aprovação independente. Rejeição pode registar conferências falsas sem inventar validação. Auditor com outro papel continua sem escrita operacional.
+- Revogação do Validador 24: sessão antiga recebe 401; nova sessão MFA autentica, mas o papel já não autoriza. Inicialização da dupla 27/28 pelo terceiro aprovador 29; substituição atómica 28→30; dupla atual 27/30, terceiro negado, replay negado e sessão anterior invalidada.
+- Recuperação do titular 30 por código Fortify noutra sessão, sem desativar MFA; código consumido não autentica. Desativação de MFA, eliminação e mudança de email do titular são recusadas. Auditor recupera e exporta metadados filtrados, sem snapshots privados.
+- Consumidores territoriais do Promotor corrigidos para rotas autorizadas: 11 províncias, **Cabo Delgado** selecionada, guardada e recuperada com o mesmo ID/nome; uma área geométrica devolvida pela API. O desenho no navegador continua por demonstrar.
+
+**Continuam abertos:** C37, cenários A/B e C43 na interface; contratos especializados completos e vínculos canónicos; submissão/aprovação/publicação positivas, agendamento e versão pública; filas dos coordenadores, pareceres, incidentes de suporte, decisões de recurso, SLA e governança; âmbito provincial de autorização; tokens/dispositivos; privacidade e todas as operações documentais por tipo/perfil. A submissão real do rascunho 15 responde 422 controlado por contrato Create incompleto. Revisão/correção positiva foi ensaiada com uma fixture explicitamente submetida, não com uma submissão real.
+
+API e persistência estão demonstradas nos escopos acima. Interface preparada e compilada; nenhum navegador automatizável foi inventariado, portanto não há aceitação visual. TypeScript, build QA e PHPStan passaram; {test_suite.get('tests')} testes específicos, com {test_suite.get('assertions')} asserções, passaram. A contagem não substitui a prova por requisito.
+
+Manifesto QA demonstrado: `{current['qa_manifest_sha256']}`. Manifesto ativo preservado: `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`. Não há revisão candidata fixada enquanto faltar a aceitação visual.
+
+Acumulação com a permissão administrativa antiga foi reconciliada antes da alteração: uma conta com atribuição v1 não usa a criação legada para contornar organização/tipo; a revogação não restaura automaticamente privilégio antigo mais amplo. Auditor com permissão legada continua sem escrita administrativa. Testes de compatibilidade comprovam as negações; gestores sem atribuições v1 conservam as funções anteriores. Caso C49 adicionado, sem alteração de privilégios ativos.
+
+Preservação por ID/colunas originais comprovada em 18 tabelas, incluindo conta 18, documentos e auditoria; manifesto ativo inalterado. Ativo consultado exclusivamente em transação READ ONLY (`investemoz:5432`): perfis 040000 ausentes e flag desativada; 020000 instalada, 030000/percurso ausentes, zero geometrias. **Nenhuma escrita ou alteração de privilégios ativos.** QA mantém 393 geometrias privadas; faltam 31 distritos e 157 postos, já nomeados. Publicação de camadas é separada.
+
+Evidências sanitizadas: `profiles-v1-http-qa.json`, `profiles-v1-mfa-enrollment-qa.json`, `profiles-v1-recovery-audit-qa.json`, `profiles-v1-current-version-qa.json`, `profiles-v1-preservation-qa.json`, `profiles-v1-reconciliation-proof.json`, `profiles-v1-final-qa.xml` e `profiles-v1-build-qa.log`, em `storage/app/private/investmoz-v2/portal-audit/`. Credenciais, cookies, segredos e códigos não constam dos relatórios.
+
+[Correspondência por requisito](perfis-v1-reconciliacao.md), [roteiro manual](roteiro-manual-perfis-v1.md), [backlog](backlog.md), [ativação e reversão](plano-ativacao.md). Relatório e backlog também disponíveis no servidor QA, com autenticação, em `/qa-auditoria/relatorio-executivo` e `/qa-auditoria/backlog`.
+"""
+update('relatorio-executivo.md', clean_executive)
+update('perfis-v1-reconciliacao.md', clean_executive + '\n\n### Correspondência derivada da mesma matriz\n\nEsta projeção não é outro inventário editável. Fontes e versões integrais permanecem no CSV.\n\n' + details)
+
+clean_backlog = f"""## Próximo lote: prioridade e critérios de fecho — 10/10/2026
+
+A matriz única tem 3.386 requisitos/linhas, 6.838 ocorrências e 3.380 requisitos abertos. As contagens abaixo agrupam o trabalho; mantêm o estado canónico de cada requisito. “Preparado em QA” identifica um escopo demonstrado, sem declarar todo o requisito concluído.
+
+| Grupo dos abertos | Requisitos |
+| --- | ---: |
+{groups_table}
+
+Lista integral pesquisável, derivada do mesmo CSV: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**. Acesso do gestor QA 17, Auditor 26 ou Superutilizador 27/30 com MFA. Não há permissões administrativas automáticas para o investidor.
+
+| Prioridade / requisitos | Próxima correção ou ensaio | Critério concreto |
+| --- | --- | --- |
+| P0 — AUD-UI-01; PROFILE-16/17/24 | Incorporar prova visual do login, atualização, logout, nova sessão e revogação; continuar diagnóstico sanitizado de C37. | Sessão recuperável e isolada; revogação efetiva; falha controlada sem autenticação indevida. |
+| P1 — PROFILE-05/06/07/25/30/32; AUD-DASH-01 | Executar o roteiro do dashboard, criação, recuperação, coedição, pedido/decisão e acessos negados; corrigir reproduções. | Resultado visível e persistente; mesmo ID/autor; autorização no servidor. |
+| P1 — AUD-OP-04; PROFILE-07/28 | Completar contratos Create/Patch/Response, formulário e adaptadores para entidades existentes. | Campos, regras, documentos e vínculos canónicos completos por categoria; o primeiro draft imobiliário de 24 campos não encerra o contrato. |
+| P1 — AUD-OP-03; PROFILE-08/09/11/12/19/20/21/22 | Submissão real, atribuição independente, pareceres/correções, aprovação/publicação, versão pública, incidentes e recurso. | Ciclo integral com atores distintos e contrato íntegro; nenhuma fixture de estado contada como submissão. |
+| P1 — AUD-GEO-02/03; AUD-FIELD-*; PROFILE-01/06 | Resolver os 31 distritos e 157 postos nomeados; verificar todos os seletores/mapas e âmbito provincial de autorização. | Cadastro, geometria e apresentação distinguidos por consumidor; selecionar → guardar → reabrir → mapa visível. |
+| P1 — AUD-COUNTRY-*; AUD-STATS-01 | Completar país/origem, recuperação, filtros e estatísticas por formulário. | Origem persistida e contabilizada; residência, país fiscal e origem dos fundos não substituem origem declarada. |
+| P1 — AUD-OP-02; AUD-LIB-01/02; AUD-SCAN-01 | Completar operações documentais, PDFs, partilhas e derivadas por tipo/perfil. | Scan próprio, permissões, revogação e recuperação por hash; original preservado. ClamD real já demonstrado não encerra operações restantes. |
+| P1 — PROFILE-13/14/15/18/23/26/31 | Completar operações críticas, concorrência da dupla, elevação, revalidação, privacidade, governança e instalação autenticada 040000. | Prévia, autorização, aplicação sem duplicação, recuperação e reversão verificadas; instalação separada da disponibilização. |
+
+**Decisões concretas para futura ativação:** PROFILE-29 — quais funções dos gestores ativos correspondem a Validador, Publicador, Auditor ou administração controlada; quem serão os dois titulares reais e o terceiro aprovador do bootstrap? PROFILE-22 — quais valores, versões e vigência dos SLA, tolerâncias e ciclos por tipo? PROFILE-16 — qual instância fará a recuperação de emergência se ambos perderem todos os meios? As cinco decisões canónicas incluem ainda as quatro pendências anteriores, preservadas por ID. Estas perguntas não impedem desenvolvimento QA independente.
+
+A edição por outros Promotores autorizados da mesma organização já foi decidida e aplicada em QA. Novas jornadas educativas não foram iniciadas. Workflow e contratos especializados continuam no backlog. [Correspondência e evidência](perfis-v1-reconciliacao.md), [roteiro](roteiro-manual-perfis-v1.md), [ativação](plano-ativacao.md).
+"""
+update('backlog.md', clean_backlog)
+
+clean_activation = f"""## Sequência consolidada: instalações, disponibilização e reversão — 10/10/2026
+
+Preparação exclusivamente em QA. Nenhuma ativação autorizada e nenhuma revisão candidata fixada. As provas `ready` anteriores são históricas: os fingerprints incluem agora as regras de perfis, portanto não comprovam esta revisão nem instalação funcional.
+
+1. Incorporar os ensaios visuais C37/C43/A/B, perfis e consumidores; corrigir falhas; fixar revisão, manifestos e configuração. Reconciliar permissões legadas e titulares reais. Completar os contratos antes de disponibilizar submissão/aprovação/publicação.
+2. Renovar backup da base, originais, ficheiros e configuração/chaves após fixar a revisão. Restaurar numa nova QA guardada e comparar IDs, relações, hashes, schema, compatibilidade e reversão. Usar as contagens reais do momento. A cópia de 09/10 não é apresentada como backup renovado desta candidata.
+3. **Gestão 020000:** já instalada no ativo; não repetir. Atalhos C43 e primeiro rascunho imobiliário não exigem essa instalação. Disponibilização dos atalhos por `PORTAL_OPPORTUNITY_DASHBOARD_ACCESS_ENABLED`, separada do schema; preservar gestores verificados e funções legadas reconciliadas.
+4. **Recursos 030000:** se ausente, prévia e aplicação autenticadas por GET/POST `/management/opportunity-resources-install`, com provas atuais. Esperado: três tabelas de associação, uma coluna em documents, uma função e três triggers; zero originais/recursos criados automaticamente. ClamD/GD/WebP são dependências das operações binárias afetadas. Instalação não confirma scans, divulgação ou publicação.
+5. **Perfis 040000:** falta concluir o mecanismo autenticado de instalação e o bootstrap ativo em QA. A migration guardada está preparada, sem autorização para execução ativa indiscriminada. Esperado: quatro tabelas de autorização ligadas às entidades existentes; uma coluna em users e três em opportunities; uma função e dois triggers. **Zero contas, atribuições ou titulares reais criados automaticamente.** Depende da gestão 020000; recursos 030000 são necessários para os respetivos consumidores. A cerimónia designa dois titulares reais com MFA e terceiro aprovador independente, sem converter a allowlist antiga. `PORTAL_PROFILE_ACCESS_ENABLED` é disponibilização separada. QA já instalada: não repetir migration ou bootstrap; dupla sintética atual 27/30.
+6. **Balcão e percurso:** instalar apenas dependências ausentes pelo mecanismo autenticado existente; 190000 prepara o percurso e múltiplos investimentos. Preservar cinco fases e 19 etapas. Instalação não disponibiliza nem conclui I1–I3; flags, assets, rotas e cenários A/B visuais têm provas próprias. Não depende de CRM externo.
+7. **Importação cartográfica:** prévia, correspondências, hash e aplicação autenticada privada/idempotente/auditável, usando territórios existentes. QA: 393 de 581 geometrias esperadas — províncias 11/11, distritos 128/159, postos 254/411; pendentes 0/31/157, com os 188 nomes em correspondencias-cartograficas.md. A prévia ativa calcula a interseção inequívoca do alvo, sem copiar contagens QA cegamente. Publicação das camadas é outra ação. Importação não ativa cálculos fiscais; fonte oficial aceite não requer nova validação de credibilidade.
+8. Somente após futura autorização ativa, verificar código/compilação/cache/cookies/guards, contagens antes/depois, auditoria, originais, versão pública e recuperação dos percursos no alvo aprovado.
+
+**Reversão:** desativar flags específicas e interromper novas operações, mantendo código de autorização compatível com os privados. Não regressar a código que os exponha. 040000 recusa `down` se há dados/pedidos/dupla/histórico; depois de uso, preservar tabelas ou reconciliar restauro numa janela autorizada. Revogações e substituições permanecem rastreáveis. Não restaurar um backup antigo apagando dados posteriores. 030000 só reverte antes de uso; percurso e importação usam as reversões existentes, preservando relações/originais. Reversão da publicação de camadas é independente da importação.
+
+Fingerprints preparados, sem fixação de candidata:
+
+{chr(10).join('- '+name+': `'+digest+'`' for name,digest in preservation['fingerprints'].items())}
+
+Manifesto QA `{current['qa_manifest_sha256']}`; manifesto ativo `75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94` preservado. Provas específicas precisam corresponder à revisão final e ao alvo real.
+"""
+update('plano-ativacao.md', clean_activation)
+
+clean_manual = """# Ensaio manual de perfis v1 — QA exclusiva
+
+**Endereço inicial: http://127.0.0.1:18097/dashboard.** Não usar portal-investidor.test nem outra porta. O servidor verifica `desk_restore_20261009_174726_test:55441` antes de escritas. Em Network, confirmar o header `X-Investmoz-QA-Target` de uma resposta de página/API. Capturas devem omitir Cookie, X-XSRF-TOKEN, Authorization, credenciais, segredos e corpos de login/MFA.
+
+Credenciais e material MFA ficam apenas no ficheiro local privado `storage/app/private/investmoz-v2/portal-audit/profiles-v1-actors-private.json`. Consulte no editor e no autenticador local; não os copie para a conversa. Todas as contas sintéticas foram configuradas normalmente por Fortify sob a chave QA estável. Não gerar outra chave nem desativar MFA.
+
+## Contas e estado atual
+
+| Conta QA | Estado após os ensaios |
+| --- | --- |
+| 20 | Público, sem criação de oportunidades |
+| 21 | Promotor da organização A; autor do rascunho 15 |
+| 22 | Outro Promotor autorizado da organização A; coedição |
+| 23 | Promotor da organização B; acesso à oportunidade 15 negado |
+| 24 | Validador revogado; conta e login MFA preservados |
+| 25 | Publicador; sem edição técnica ou aprovação de rascunho |
+| 26 | Auditor; leitura e exportação de metadados |
+| 27 e 30 | Os dois Superutilizadores atuais |
+| 28 | Titular substituído; conta preservada, administração negada |
+| 29 | Terceiro aprovador do bootstrap QA; não é Superutilizador |
+| 31 | Promotor + Validador + Auditor; restrição de leitura prevalece |
+
+## Primeiro ensaio: Promotor, recuperação e coedição
+
+1. Numa sessão QA isolada, entrar como 21: login → MFA → dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”. Atualizar a página mantém a sessão; registar se volta ao login.
+2. Clicar “Minhas oportunidades” → abrir 15 → editar. Esperado: mesmo ID, organização e rascunho; título editado por 22 e Cabo Delgado recuperados. O dossier privado não se transforma em oportunidade publicada.
+3. Selecionar província/distrito disponíveis e conferir o mapa/estado de cobertura. Guardar com fundamento. Esperado: mensagem de gravação; mudar o pai limpa filhos. Limite administrativo não representa perímetro do terreno.
+4. Logout → nova sessão/login MFA 21 → dashboard → Minhas → 15. Esperado: campo, nome, ID, versão e mapa recuperados. Separar prova do desenho, API e persistência.
+5. Noutra sessão, 22 → dashboard → Minhas → 15 → editar/guardar. Esperado: autorizado; autor 21 preservado e editor 22 registado. Nova sessão 21 recupera a edição.
+6. Como 23, abrir o URL da oportunidade 15. Esperado: 403 controlado sem conteúdo da organização A. Como 31, leitura permitida e gravação negada; os dados não mudam. Como 20, criação não aparece e acesso direto é negado.
+7. Como 21, solicitar arquivo com razão. Esperado: pedido persistido, estado draft mantido. Promotor não ganha exclusão/restauro. Submissão e publicação completas continuam indisponíveis pelo contrato; não interpretar isso como falha MFA/C37.
+
+## Pedido de Promotor e decisão independente
+
+1. Como 20: dashboard → “Solicitar perfil de Promotor” → `/perfil/promotor`. Esperado: somente pedidos e comprovativos próprios. Se necessário, preparar um anexo sintético privado no dossier do Balcão; aguardar scan clean real.
+2. Escolher representação, organização existente autorizada quando aplicável, tipos, comprovativo e fundamento. Submeter. Esperado: ID e estado pending; nenhuma criação autorizada antes da decisão.
+3. Logout/nova sessão 20 → acompanhamento. Esperado: mesmo pedido recuperado. Antes de repetir por erro de interface, conferir o acompanhamento; a mesma chave não duplica o pedido.
+4. Noutra sessão, 27 ou 30 → Gestão de perfis → consultar comprovativo → conferir identidade, representação e documentos → escolher tipos → decidir com razão. Declarar apenas conferências efetivamente realizadas. Rejeição pode manter conferências falsas e não concede perfil. Aprovação própria é negada.
+5. Nova sessão 20 após aprovação → dashboard. Esperado: Minhas/Nova para o âmbito e tipos aprovados; outro tipo/organização continua negado. Documentos e decisão original permanecem.
+
+## Revisão, auditoria e operações críticas
+
+1. Como 25, consultar 15. Esperado: sem edição técnica, aprovação ou publicação de draft. A publicação positiva integral ainda depende do contrato completo; não fabricar estados para encerrar o teste.
+2. Como 26 → Auditoria → filtrar `superuser_replaced` → exportar JSON. Esperado: metadados da substituição 28→30, sem segredos ou snapshots privados; exportação auditada. Escrita operacional continua negada com outros papéis.
+3. Como 27/30 → Gestão de perfis. Esperado: dupla 27/30, alertas, pedidos, atribuições e formulários. Como 28, administração negada; como 24, login MFA válido mas papel revogado.
+4. Para ensaio positivo do Validador, atribuir explicitamente 24 pelo 27/30, com tipos e fundamento. Preservar a revogação anterior. Filas e completude ainda pendentes. Ao terminar, revogar a nova atribuição: sessão antiga perde acesso; nova sessão conserva autenticação, sem o papel.
+5. Para uma substituição adicional, usar candidato sintético QA com MFA. Preparar → outro titular aprova → aplicar. Esperado: sempre dois titulares, terceiro isolado negado, replay negado e acesso anterior revogado. Não escolher titulares reais nem repetir bootstrap para regressar a 28.
+6. Elevação exige outro titular, ação/objeto exatos, papel operacional e MFA recente. Não remove impedimentos de autoria/Auditor. Após 15 minutos, decisão administrativa exige novo MFA por logout/login QA; não desativar MFA.
+7. Recuperação do titular usa código Fortify local, sem captura. Código consumido não autentica. Emergência quando ambos perdem todos os meios permanece uma decisão/procedimento institucional.
+
+## Registar os resultados na mesma matriz
+
+Por ação: conta QA, URL, hora UTC, ID, esperado, observado, mensagem visível, status API e campo após nova sessão. Omitir segredos. Associar ao AUD-PROFILE correspondente; falhas adicionais entram nos casos de reprodução. C37 e A/B não são fechados por este roteiro.
+
+Os cenários A/B mantêm as cinco fases e 19 etapas do roteiro existente: criação → gravação → nova sessão → recuperação → aplicabilidade → ferramenta → resultado no dossier → Balcão → acompanhamento, incluindo tarefa independente em paralelo e ausência de mistura/acesso indevido.
+
+Relatório e backlog autenticados: http://127.0.0.1:18097/qa-auditoria/relatorio-executivo e http://127.0.0.1:18097/qa-auditoria/backlog. Lista da matriz: `/qa-auditoria/pedidos-abertos`. Acesso do gestor QA 17, Auditor 26 ou Super 27/30 com MFA; Público e Promotor isolado não recebem acesso administrativo.
+"""
+(DOCS / 'roteiro-manual-perfis-v1.md').write_text(clean_manual, encoding='utf-8')
+
+
+clean_cases = """## Reproduções adicionais de perfis — 10/10/2026
+
+C37 permanece pendente; não houve nova tentativa da conta 18 nem fecho visual. C43/C44 preservados.
+
+| Caso / requisito | Reprodução | Esperado | Observado e causa | Correção/prova | Pendente |
+| --- | --- | --- | --- | --- | --- |
+| C45 — PROFILE-05/06/25, AUD-GEO-03 | Promotor 21: dashboard → Nova → seletor/mapa; comparar chamadas territoriais. | Perfil autorizado consulta, grava e recupera território/geometria. | Consumidor chamava rotas management reservadas a manage-portal. Inspeção de código/rotas; nenhuma captura visual anterior. | Alias autorizados reutilizam serviços: 11 províncias, Cabo Delgado guardada/recuperada, uma área API. profiles-v1-current-version-qa.json. | Desenho/cliques por perfil e restantes consumidores. |
+| C46 — PROFILE-06/07/10/29 | Gestor sem perfil: API administrativa de contexto da oportunidade privada; território, prévia de origem e subjects. | Allowlist legada não revela/edita o privado v1. | Rotas auxiliares tinham apenas can:manage-portal, sem política do registo. Lacuna identificada em código, sem realizar escrita indevida. | Middleware cobre aliases/payload; subjects/dashboard/catalog usam âmbito. Testes 403/lista vazia. | Outras relações/filas e âmbito provincial. |
+| C47 — PROFILE-04 | Rejeitar pedido com approved_types=[] e conferências false. | Rejeição fundamentada sem inventar conferência. | Ensaio respondeu 422: approved_types required rejeitava array vazio. | present|array; não-vazio só na aprovação; accepted_if só approved. Teste rejeita sem conceder e preserva conferência false; decisão própria 403. | Decisão na interface. |
+| C48 — PROFILE-15/16/24/26 | Titular 30: DELETE MFA, DELETE conta, PATCH email. | Manter MFA obrigatório, dupla e histórico. | Regra específica da identidade privilegiada v1 não existia. Lacuna identificada em código; nunca se desativou MFA para ensaio. | ProtectPrivilegedIdentity, 403 e auditoria; recovery Fortify noutra sessão/reuse negado; trigger DELETE testado. | Visual e recuperação institucional de emergência. |
+| C49 — PROFILE-10/29 | Conta sintética com papéis v1 e allowlist legada: abrir Nova legada, POST draft legado; depois escrita administrativa com Auditor. | Não contornar organização/tipo nem a restrição do Auditor pela acumulação. | Exceção legada podia autorizar escrita mais ampla. Identificada em código, sem usar conta ativa ou criar dados fora do âmbito. | Decisão documentada antes da correção; legacyWriteAllowed usa histórico; 403 na criação e escrita, atalho legado ausente nas props. Gestor sem atribuição v1 preservado. | Interface, conciliação dos gestores reais e consumidores restantes. |
+
+Submissão real do rascunho 15 → 422 por contrato Create ausente é lacuna funcional mantida, não falha de MFA/autenticação. A fixture de revisão não demonstra submissão integral. Evidências por critério em profiles-v1-final-qa.xml, http-qa, recovery-audit, current-version e preservation; JSON/HTML não substitui interface.
+"""
+update('casos-reproducao.md', clean_cases)
+clean_coverage = """## Cobertura após perfis v1 — 10/10/2026
+
+I0–I3 permanecem em QA. Cinco fases e 19 etapas preservadas, sem renumeração. C37, A/B e C43 visuais continuam pendentes. A autorização organizacional reutiliza OpportunityManagement, Resources, Fortify e entidades existentes; nenhuma jornada educativa nova foi iniciada.
+
+- Interface: preparada e compilada, sem observação no navegador. Roteiro manual de perfis inclui acessos permitidos/negados; A/B preservam o roteiro existente.
+- API: links descobertos no dashboard, rascunho 15 recuperado noutra sessão, coedição 22 e negações por tipo/organização/múltiplos papéis. Seletores autorizados e geometria do Promotor funcionam; submissão integral permanece bloqueada por contrato incompleto.
+- Persistência: autor, ID, versão e histórico preservados; Cabo Delgado recuperada com o mesmo ID/nome. Pedido de Promotor, comprovativos, auditoria, revogação e dupla demonstrados nos escopos descritos.
+- Documentos: quatro comprovativos sintéticos com ClamD real e hash recuperável; não generalizar às operações restantes. Originais anteriores preservados em 18 tabelas.
+- Ativo: exclusivamente READ ONLY, sem instalação/flag de perfis. 020000 instalada; recursos/percurso ainda ausentes. Mesma matriz: 3.386 requisitos, 6.838 ocorrências.
+
+Coordenadores, pareceristas, suporte e recurso estão explicitamente mapeados na reconciliação. Filas, decisões, SLA e incidentes funcionais continuam parciais ou não implementados no backlog. 393 geometrias privadas QA não encerram a integração visual; permanecem 31 distritos/157 postos nomeados.
+"""
+update('cobertura-percursos-i0-i3.md', clean_coverage)
+update('execucao-percurso-i1-i3.md', clean_coverage)
+print(json.dumps({'updated_documents': 8, 'profile_requirements': len(profiles), 'canonical_requirements': counts['requisitos'], 'active_writes': 0, 'visual_acceptance_pending': True}))
+
+# The dated extraction report is historical once the canonical workflow increment exists.
+if (PRIVATE / 'opportunity-workflow-http-qa.json').exists():
+ import runpy
+ runpy.run_path(str(ROOT / 'tools/portal-audit-workflow-docs.py'), run_name='__main__')
diff --git a/tools/portal-audit-profiles-update.py b/tools/portal-audit-profiles-update.py
new file mode 100644
index 00000000..aec61f62
--- /dev/null
+++ b/tools/portal-audit-profiles-update.py
@@ -0,0 +1,375 @@
+"""Reconcile both profile specifications in the existing matrix; preserve every source occurrence."""
+import collections
+import csv
+import hashlib
+import json
+import re
+import shutil
+import subprocess
+import sys
+import zipfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+sys.stdout.reconfigure(encoding='utf-8')
+csv.field_size_limit(16 * 1024 * 1024)
+ROOT = Path(__file__).resolve().parent.parent
+DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+SOURCE = Path('C:/Mac/Home/Documents/TEMPO/Portal Tempo/Servicos Tempo')
+MATRIX = DOCS / 'matriz-requisitos.csv'
+rows = list(csv.DictReader(MATRIX.open(encoding='utf-8-sig', newline='')))
+fields = list(rows[0])
+baseline = PRIVATE / 'profiles-v1-matrix-before.csv'
+if not baseline.exists():
+ shutil.copyfile(MATRIX, baseline)
+before = list(csv.DictReader(baseline.open(encoding='utf-8-sig', newline='')))
+assert len(before) == 3354
+assert sum(int(r['Quantidade de linhas de origem']) for r in before) == 5830
+
+# Reconcile the full accessible corpus, including embedded original media/attachments.
+inventory_path = DOCS / 'inventario-fontes.csv'
+inventory = list(csv.DictReader(inventory_path.open(encoding='utf-8-sig', newline='')))
+inventory_fields = list(inventory[0])
+seen = {(r['Exemplar/caminho'], r['SHA256']) for r in inventory}
+paths = subprocess.check_output(['rg', '--files', '--hidden', '--no-ignore', str(SOURCE)], text=True, encoding='utf-8').splitlines()
+errors = []
+new_inventory = []
+def inventory_entry(name, data, kind):
+ digest = hashlib.sha256(data).hexdigest()
+ if (name, digest) in seen:
+ return
+ seen.add((name, digest))
+ new_inventory.append(dict(zip(inventory_fields, [name, str(len(data)), digest, kind,
+ 'Inventário complementar 10/10/2026; versões anteriores preservadas',
+ 'Acessível localmente; importação/publicação não inferida', 'Nenhum cálculo ativado',
+ 'Situação jurídica/documental não inferida do inventário', 'Exemplar identificado por SHA256'])))
+for filename in paths:
+ path = Path(filename)
+ try:
+ raw = path.read_bytes()
+ inventory_entry(str(path), raw, 'original')
+ if not path.name.startswith('~$') and path.suffix.lower() in {'.docx', '.xlsx', '.pptx', '.docm', '.xlsm', '.pptm'}:
+ with zipfile.ZipFile(path) as archive:
+ for member in archive.namelist():
+ if '/media/' in member or '/embeddings/' in member:
+ inventory_entry(str(path) + '#' + member, archive.read(member), 'anexo embebido')
+ except (OSError, zipfile.BadZipFile) as error:
+ errors.append({'path': str(path), 'error_type': type(error).__name__})
+inventory.extend(new_inventory)
+with inventory_path.open('w', encoding='utf-8-sig', newline='') as handle:
+ writer = csv.DictWriter(handle, fieldnames=inventory_fields); writer.writeheader(); writer.writerows(inventory)
+
+specs = [
+ ('PROFILEV1', 'Gestao de perfis investeMOZ v1.docx', 'profiles-v1-source.txt', 'f9e0f6280566fed8b52d0b36bb814a82e11976fec9ea9f62d64611ff8c824b38', 530),
+ ('PROFILEOLD', 'Gestao de perfis investeMOZ.docx', 'profiles-prior-source.txt', '283a32f4c4b02bdfd9318a9174268224eeefac4349c49e3171545707bd222855', 471),
+]
+sources = []
+for prefix, name, extract, digest, total in specs:
+ path = SOURCE / 'prompt/novos' / name
+ raw = path.read_bytes()
+ assert hashlib.sha256(raw).hexdigest() == digest, 'Source changed; preserve and reconcile a new version before updating.'
+ original_dir = PRIVATE / 'profile-source-originals'; original_dir.mkdir(exist_ok=True)
+ exemplar = original_dir / (digest + '.docx')
+ if not exemplar.exists(): exemplar.write_bytes(raw)
+ lines = (PRIVATE / extract).read_text(encoding='utf-8').splitlines()
+ parsed = [re.match(r'^(\d+): ?(.*)$', line) for line in lines]
+ parsed = [m for m in parsed if m]
+ assert len(parsed) == total
+ sources.append({'prefix': prefix, 'name': name, 'path': str(path), 'sha256': digest,
+ 'paragraphs': [(int(m[1]), m[2]) for m in parsed], 'original_preserved': str(exemplar), 'read_integrally': True})
+
+# One verifiable requirement per entry. Full source paragraphs are references, not new requirements.
+requirements = [
+ (1, 'Seis perfis sobre identidades existentes, com RBAC e ABAC', 'parcial',
+ 'PortalProfileAccess; users/Fortify, organizations/memberships, quatro atribuições operacionais e dupla controlada; público derivado de conta verificada.',
+ 'Doze atores normais MFA e consultas por perfil no servidor QA; schema ligado às entidades canónicas.',
+ 'Âmbito provincial ainda não modelado; migração reconciliada dos gestores legados e aceitação visual por perfil.',
+ 'Cada perfil corresponde a uma identidade existente e a regras de servidor; nenhum cadastro de identidades duplicado.'),
+ (2, 'Utilizador público: consulta, favoritos/alertas e pedidos próprios', 'parcial',
+ 'Capacidades públicas existentes; pedido próprio de Promotor reutiliza conta verificada.',
+ 'Conta20: dashboard→pedido, criação403 e consulta de pedido alheio403; favoritos/alertas não ensaiados neste lote.',
+ 'Demonstrar favoritos/alertas e todos os pedidos pessoais na interface; alternativa de confirmação por telefone da v1 ainda não implementada, verificação de email existente preservada.',
+ 'Consulta e pedidos próprios funcionam; criação/edição/decisão de oportunidades são negadas ao público.'),
+ (3, 'Solicitar perfil de Promotor com representação, tipos e comprovativos', 'parcial',
+ 'PortalProfileAdministration::request; documentos canónicos próprios/hash/scan, chave idempotente, âmbito individual ou organização representada.',
+ 'Contas21/22/23/31: quatro pedidos, replay sem duplicação, recuperação noutra sessão, quatro comprovativos sintéticos com ClamD real e recuperação por hash.',
+ 'Verificação visual do formulário, submissão de tipos adicionais e regras institucionais de comprovativos por representação.',
+ 'Pedido guarda representação/tipos/comprovativos, fica recuperável e não concede o papel por si só.'),
+ (4, 'Decisão independente do pedido de Promotor e tipos aprovados', 'parcial',
+ 'Fila administrativa, consulta privada dos comprovativos por VerifiedDocumentBinary, versão e atestações auditadas; sem autoaprovação.',
+ 'Super27 consulta originais por hash e aprova quatro pedidos de outros atores; teste nega decisão própria e regista rejeição com verificações falsas sem inventar confirmação.',
+ 'Aceitação visual da fila e decisões; não foram validadas identidades reais, apenas documentos sintéticos QA.',
+ 'Somente aprovador distinto com MFA confirma identidade/representação/documentos e concede os tipos efetivamente pedidos e aprovados.'),
+ (5, 'Navegação por perfil a partir do dashboard', 'parcial',
+ 'ProfileNavigation e props de autorização partilhadas; páginas existentes reutilizadas em /minhas-oportunidades.',
+ 'DashboardHTTP21 devolve Minhas oportunidades/Nova oportunidade;20 devolve Solicitar perfil; ensaio segue os URLs devolvidos, sem depender de rota conhecida previamente.',
+ 'Cliques, renderização, responsividade e resultado visível no navegador; C37 não fechado.',
+ 'Promotor autorizado descobre lista/criação no dashboard; os outros descobrem pedido e acompanhamento sem obter criação.'),
+ (6, 'Edição organizacional por outros Promotores e âmbito pessoal exclusivo', 'parcial',
+ 'OpportunityManagement/Resources reutilizados; owner_user_id preservado, contributors e membership de escrita em servidor.',
+ 'Autor21 cria oportunidade15; colega22 autorizado edita, recuperação mantémID/autor;23 fora da organização403. Seletores/mapas mudam para endpointsautorizadosv1:11províncias, seleçãoCaboDelgado gravada/recuperada noutra sessão com geometriaAPI. Teste de representação revogada nega escrita.',
+ 'Percurso visual e coedição dos recursos por operação; restrições provinciais permanecem separadas.',
+ 'Outros Promotores autorizados da organização editam rascunho/correção; pessoal sem organização só pelo titular; histórico preservado.'),
+ (7, 'Autorizações por tipo e representação sem transferência silenciosa', 'parcial',
+ 'Tipos em atribuições e pedidos; organização imutável na edição, autor/workflow/status proibidos no payload.',
+ 'HTTP22: mudança para tipo não aprovado403 e transferência de organização403; fixture testa isolamento de tipos.',
+ 'Demonstrar todos os contratos especializados e seus campos/validadores; seleção do tipo não os encerra.',
+ 'Servidor nega qualquer criação/edição fora dos tipos aprovados ou da representação; novos tipos exigem decisão.'),
+ (8, 'Estados, razões, versões e dependências reais do workflow', 'parcial',
+ 'OpportunityProfileWorkflow reutiliza códigos/management_version/etag/audit_events; revisão, correção, parecer, rejeição/suspensão/arquivo e pedidos segregados.',
+ 'HTTP: pedido de arquivo guarda e mantémdraft, submissão422 com lacuna explícita; fixture submetida inicia revisão, pede correção e recupera edição.',
+ 'Submissão completa, aprovação/publicação, incidentes e conservação de versão pública ainda não demonstradas; fixture não é submissão real.',
+ 'Transições válidas e fundamentadas preservam versão/história; inválidas são negadas; preparação não se confunde com decisão externa.'),
+ (9, 'Impedir aprovação própria, conflitos de organização e publicação pelo aprovador', 'parcial',
+ 'Autor, contributors e membership da organização impedem revisão; publicação verifica aprovador da mesma versão; autorizações rechecadas sob lock.',
+ 'Teste autor com Promotor+Validador+Publicador continua403; regras editor/representação verificadas no serviço.',
+ 'Publicação real permanece bloqueada pelo contrato; testar ciclo completo e reatribuição independente com versão aprovada real.',
+ 'Autor/editor/representante não aprova; aprovador não publica a mesma versão; elevação não remove esses impedimentos.'),
+ (10, 'Acumulação de papéis com negação prevalecente', 'parcial',
+ 'Auditor nega escrita operacional; Super exige papel operacional mais elevação independente; papéis não se somam para ultrapassar restrições.',
+ 'Conta31 Promotor+Validador+Auditor lê e recebe403 na edição;27 Super sem Promotor/elevação recebe403 na criação. Fixture com papéis v1 e allowlist legada: criação fora do âmbito403, dashboard sem criação legada; Auditor nega escrita administrativa. Revogação/expiração não restaura permissão legada automaticamente.',
+ 'Demonstração visual e combinações operacionais adicionais com elevação aprovada.',
+ 'A acumulação nunca autoriza ato negado por autoria, organização, tipo, estado, independência ou Auditor.'),
+ (11, 'Validador: revisão atribuída, MFA, correções e decisão', 'parcial',
+ 'Papel validator com âmbito/tipos e responsabilidades compatíveis; MFA confirmado exigido na atribuição e recente na operação.',
+ '24 aprovado inicialmente, aprovação de draft409, revogado depois; fixture independente revisa/corrige e recupera nova versão; semMFA403.',
+ 'Fila de atribuição e completude normativa, decisão positiva integral e interface.',
+ 'Validador independente e com MFA só decide âmbito/tipo/estado permitidos; justificação e itens de correção persistem.'),
+ (12, 'Publicador: versão aprovada, suspensão/arquivo e segregação', 'parcial',
+ 'Papel publisher, MFA recente, independência; conteúdo técnico não editável; publicar bloqueado se completude/versão faltam.',
+ '25 publica draft409; fixture confirma estado incompatível; todos os atos positivos de publicação integral continuam pendentes.',
+ 'Publicação e agendamento, revisão de divulgação, suspensão urgente/retificação e prova da versão pública.',
+ 'Publicar somente versão completa aprovada por outro ator; suspender/arquivar com razão sem alterar original nem decisão externa.'),
+ (13, 'Auditor: consulta filtrada/exportação e ausência de escrita', 'parcial',
+ '/perfis/auditoria usa audit_events existentes, filtros e JSON minimizado; Auditor conserva impedimento de escrita.',
+ '26 recupera substituição filtrada e exporta metadados sem snapshots privados;20 recebe403;31 multirrole edição403.',
+ 'Interface, exportação ampliada autorizada por classificação e consulta dos restantes domínios administrativos.',
+ 'Filtros retornam só metadados autorizados e exportação rastreável; nenhum botão/API permite escrita operacional ao Auditor.'),
+ (14, 'Superutilizador: administração controlada e elevação temporária', 'parcial',
+ 'PortalSuperusers/Administration; MFA recente, motivo, aprovação independente e validade15min; aprovador deve continuar na dupla.',
+ '27 administra pedidos/papéis, autoaprovação403, criação sem papel403; elevação API preparada, ainda sem ato operacional positivo completo.',
+ 'Demonstração da elevação completa, expiração, scope/action exatos e interface de administração.',
+ 'Super administra sem operar automaticamente; elevação independente expira e não substitui papel operacional ou segregação.'),
+ (15, 'Exatamente dois Superutilizadores: inicialização e substituição atómica', 'parcial',
+ 'Dupla singleton ligada a users, CHECK distintos, triggerDELETE/TRUNCATE, versão/lock, aprovação e atualização única.',
+ 'Inicialização27/28 pelo29; terceira atribuição422; substituição28→30 com aprovação28 independente de27, dupla27/30; replay409, sessão28invalidada. TriggerDELETE testado.',
+ 'Interface, testes concorrentes em sessões simultâneas e cerimónia ativa com titulares reais ainda não designados.',
+ 'Após inicialização existem sempre dois titulares distintos; nem terceiro, remoção isolada, autoaprovação ou replay altera essa cardinalidade.'),
+ (16, 'Recuperar acesso preservando MFA e dupla', 'parcial',
+ 'Códigos de recuperação Fortify e substituição independente; bloqueio de desativaçãoMFA, mudançaemail/eliminação de titular.',
+ '30 recupera sessãoMFA noutra sessão pelo códigoFortify; reutilização422 sem autenticação; DELETE-MFA/conta e PATCHemail403.',
+ 'Procedimento institucional quando ambos perdem todos os meios; aceitação visual e guarda local dos códigos sem os transmitir.',
+ 'Recuperação normal mantém MFA e dois titulares; código consumido não autentica; emergência não é desativaçãoMFA ou key:generate.'),
+ (17, 'Revogação imediata com histórico e invalidação de sessões/tokens', 'parcial',
+ 'Atribuição retida, revision de autorização por conta, remember_token revogado; adaptação sessions/personal_access_tokens quando presentes.',
+ '24 antigo cookie401; nova sessãoMFA autentica mas acesso de papel403;28 substituído igual. Histórico original preservado.',
+ 'Tokens pessoais não instalados/ensaiados no alvo, dispositivos/integradores e interface por consumidor.',
+ 'Revogar invalida sessões e credenciais de acesso aplicáveis sem apagar conta, MFA, documentos, autoria ou decisões.'),
+ (18, 'Validade, reavaliação por inatividade e documentação expirada', 'parcial',
+ 'starts_at/expires_at/revoked_at consultados a cada pedido; atribuições documentadas sem cache de autorização.',
+ 'Fixture de papel expirado não autoriza; MFA antigo não permite decisão.',
+ 'Revalidação/inatividade/expiração documental, parâmetros aprovados e avisos; não inventar prazos.',
+ 'Atribuição expirada ou representação revogada deixa de autorizar; reavaliação usa prazos/regra versionados aprovados.'),
+ (19, 'Coordenadores de validação/publicação e pareceres técnico-jurídicos', 'não implementado',
+ 'Responsabilidades mapeadas e compatibilidade por papel validadas; entidades existentes de tarefa/auditoria a reutilizar.',
+ 'Responsabilidade validation_coordinator em Auditor422; papéis/responsabilidades armazenáveis, filas e reatribuições não implementadas.',
+ 'Implementar filas/atribuição, conflito, disponibilidade, parecer e escalamento sem novos perfis ou identidades.',
+ 'Coordenador autorizado atribui/reencaminha; parecerista responde; impedimentos persistem; ação visível e recuperável.'),
+ (20, 'Suporte técnico, incidentes e preservação da submissão', 'não implementado',
+ 'Balcão/tarefas/audit_events existentes; suporte mapeado sem acesso documental automático; nenhum gestor fictício.',
+ 'Correspondência documental preparada; protocolo de incidentes da submissão não implementado neste workflow.',
+ 'Incidentes recuperáveis, suporte atribuído, falha de submissão/ficheiro sem perda, alertas e estados próprios.',
+ 'Falha técnica conserva submissão/versão, abre incidente e encaminha sem dar ao suporte permissão de decisão ou dados indevidos.'),
+ (21, 'Recurso com instância independente e conservação da decisão original', 'parcial',
+ 'Responsabilidade appeal_reviewer de Validador e pedido de recurso no workflow_context existente.',
+ 'API de pedido prevista apenas rejected; decisão independente e percurso positivo de recurso não demonstrados.',
+ 'Fila/revisor distinto do decisor inicial, resposta/motivo/versionamento e recuperação visual.',
+ 'Recurso não sobrescreve decisão; revisor distinto e autorizado decide com razão, sem publicar.'),
+ (22, 'Prazos, tolerâncias e ciclos aprovados/configuráveis/versionados', 'parcial',
+ 'policy_version nas atribuições e workflow, correction_cycles preservados; ausência de parâmetros não encerra processos automaticamente.',
+ 'Versão de autorização profiles-v1-20261010 e correção auditadas; gestão/efeito de parâmetros ainda não implementados.',
+ 'Tela/versionamento/governança e adaptação dos processos antigos; valores institucionais aprovados.',
+ 'Alterar SLA/limites requer aprovação, vigência e versão; processo antigo conserva regra aplicável e nenhuma configuração inventa prazo.'),
+ (23, 'Auditoria integral, razões, origem e alertas de segurança', 'parcial',
+ 'audit_events existente com ator/IP/tempo/correlação/política/razão e before-after relevantes; denegação sanitizada sem corpoauth.',
+ 'HTTPs e fixture recuperam decisão/revogação/substituição e alerta administrativo; exportação minimizada não inclui segredos.',
+ 'Cobertura dos fluxos ainda ausentes, exportação autorizada auditada, alertas operacionais e interface.',
+ 'Cada decisão/crítica/negação guarda contexto rastreável e antes/depois aplicável; leitura/exportação não expõe segredos.'),
+ (24, 'MFA e segurança de sessão/autenticação sem contornar C37', 'parcial',
+ 'Fortify existente, MFA normal, sessão QA/cookie isolados e epochs; proteção de MFA obrigatório em papéis críticos.',
+ 'Doze contas confirmamMFA pelo servidor18097, nova sessão e recuperação30 comprovadas; C37conta18 não repetido/fechado.',
+ 'C37/interface, duração/reautenticação operacional e restantes consumidores/devices.',
+ 'Login→MFA→sessão→reload→logout→novo login funciona visualmente sem partilha indevida de cookie ou desativaçãoMFA.'),
+ (25, 'Interface responsiva, gravação segura, erros e acompanhamento', 'parcial',
+ 'Formulários/feedback existentes reutilizados; novas páginas de pedido/admin/auditoria e contexto organizacional.',
+ 'PropsHTTP/compilação e TypeScript verificáveis; gravação/versionamentoAPI, nenhum navegador automatizável inventariado.',
+ 'Demonstração visual/acessibilidade, autosave e erros por campo nos contratos completos.',
+ 'Formulários recuperam dados, mostram ações/erros/pendências e não perdem resposta; navegação acessível por perfil.'),
+ (26, 'Privacidade, consentimento, consulta/correção/desativação', 'parcial',
+ 'users/consents/documentos privados existentes; autorizações por pedido; remoção que destruiria titulares/histórico é negada.',
+ 'Comprovativos privados por hash/autorização e não publicados; proteção de titular403; fluxo geral de desativação não ensaiado.',
+ 'Consulta/correção/desativação preservando rastreabilidade e direitos aplicáveis, retenção/documentação por tipo.',
+ 'Titular gere dados/consentimento sem perder história ou eliminar dupla; dados privados não passam ao público.'),
+ (27, 'Avaliar Keycloak antes de substituir Fortify', 'concluído e demonstrado',
+ 'Decisão arquitetural explícita em perfis-v1-reconciliacao.md; Fortify mantido e autorização funcional na aplicação.',
+ 'Código/schema confirmam Fortify e ausência de Keycloak; documentação oficial Keycloak/Laravel confrontada; necessidadeSSO/federação não demonstrada.',
+ 'Nenhuma lacuna desta avaliação restrita; eventual adoção futura exige necessidade/IDs/MFA/recuperação/migração aprovados.',
+ 'Recomendação avaliada; decisão fundamentada preserva autenticação/IDs; não declara integraçãoKeycloak ativa.'),
+ (28, 'Contratos especializados completos antes de submissão/aprovação/publicação', 'parcial',
+ 'Schema normativo110defs/novecontratos e primeiro draftimobiliário anteriores; novos gates falham de forma controlada.',
+ 'Submissão realdraft15 responde422 com lacuna do contratoCreate; versões públicas não alteradas.',
+ 'Adaptadores canónicos, camposUI/regras/vínculos/evidências especializados e ciclo completo sem fixtureestado.',
+ 'Uma oportunidade completa cumpre contrato/tipo/vínculos; submissão/revisão/aprovação/publicação integral por atores distintos é demonstrada.'),
+ (29, 'Reconciliar permissões administrativas legadas sem retirada automática', 'dependente de decisão concreta',
+ 'manage-portal preservado para registroslegados; novos privados não autorizados pela allowlist; nenhuma conta ativa promovida/revogada.',
+ 'AtivoREADONLY:rolesv1 ausentes/flagfalse; gestores2/13 existentes; fixture nega acesso legado ao novo privado sem perfil.',
+ 'Pergunta para futuraativação: que funções dos gestores ativos devem corresponder a Validador, Publicador, Auditor ou administração controlada? Quem serão os dois titulares e o aprovador da cerimónia?',
+ 'Correspondência aprovada conserva contas/história e deixa diferenças/permissões explícitas; nenhuma revogação ativa automática.'),
+ (30, 'Contas sintéticas por perfil e demonstração permitida/negada', 'parcial',
+ 'Doze contas sintéticasQA, duas organizações e quatro representações; contas antigas preservadas.',
+ 'profiles-v1-http-qa.json e recovery-audit: permitido/negado, rolesmúltiplos, troca/revogação/nova sessão sem divulgarcredenciais.',
+ 'Demonstração visual por perfil;24 agora revogado e28 substituído, não apresentar esses atores como papéis ainda ativos.',
+ 'Cada perfil tem ensaio positivo/negativo e recuperação noutra sessão; revogação/múltiplos papéis não contornam autorização.'),
+ (31, 'Instalação, disponibilização e reversão dos perfis separadas', 'parcial',
+ 'Migration040000guardada, flagQAtrue/ativofalse, fingerprints das instalações existentes incluem o código de autorização.',
+ 'QA:4tabelas,users1/opportunities3colunas,1função2triggers; ativoREADONLYausente. Baseline18tabelas originais preservadas; assetsativosSHAigual.',
+ 'Mecanismo autenticado de instalação040000 e bootstrap ativo auditável, nova prova backup/restauro/compatibilidade/reversão apósvisuais, ativação não autorizada.',
+ 'Instalar somente ausentes com prévia/provas/replay; designar dupla de forma controlada; flag não é instalação; rollback conserva dados e nega acesso aos privados.'),
+ (32, 'Arquivo/exclusão/restauro do Promotor versus gestor legado', 'parcial',
+ 'Decisão antes do código:Promotorv1 apenas solicita; Publicador decidearquivo; lifecyclegestorlegado preservado para antigos, privado não herda.',
+ 'HTTP21pedidoarquivo persiste sem mudar draft; endpointlifecycle privado403; gestorC43 anterior conserva percurso independente.',
+ 'Interfacepedido/decisãopublicador com caso válido e critério de conservação; não prometer exclusão/restauro não concedidos pela v1.',
+ 'Promotor solicita com razão, sem arquivar/apagar/restaurar; decisor autorizado registraresultado; legado mantém direitos identificados.'),
+]
+definition = {n: {'title': title, 'state': state, 'implementation': impl, 'evidence': evidence, 'gap': gap, 'acceptance': acceptance}
+ for n, title, state, impl, evidence, gap, acceptance in requirements}
+
+def classify(number, text):
+ # Tests are traced to their governing requirement. Shared structural/table paragraphs remain in the model reference.
+ if 397 <= number <= 411: return 14 if number < 407 else 17
+ if 412 <= number <= 426: return 2
+ if 427 <= number <= 431: return 28
+ if 432 <= number <= 436: return 7
+ if 437 <= number <= 441: return 6
+ if 442 <= number <= 446: return 11
+ if 447 <= number <= 466: return 9 if number >= 457 and number <= 461 else 11
+ if 467 <= number <= 486: return 12
+ if 487 <= number <= 501: return 13
+ if 508 <= number <= 517: return 15
+ if 524 <= number <= 528: return 22
+ specific = {33:1,42:15,265:15,266:15,267:15,268:15,269:15,332:2,333:3,334:4,335:7,336:18,337:22,
+ 339:10,340:6,341:28,342:8,343:8,344:10,345:14,346:23,348:24,349:7,350:24,351:1,352:25,353:26,355:1,357:27}
+ if number in specific: return specific[number]
+ value = text.lower()
+ for terms, requirement in [(['keycloak','openid','oauth'],27), (['substitui','exatamente dois','menos de dois','terceiro super'],15),
+ (['recupera','bloqueio de acesso'],16), (['revoga','invalidar sessões'],17), (['inatividade','expir'],18),
+ (['instância de recurso','recurso contra','revisor de recurso'],21), (['suporte','incidente','falha técnica'],20),
+ (['coordenador','parecer técnico','parecer jurídico','reencaminh'],19), (['sla','tolerância','limites de ciclos','prazos'],22),
+ (['autosave','responsiv','acessibil'],25), (['privacidade','consentimento','dados pessoais'],26),
+ (['segregação','própria','conflito de interesse'],9), (['acumula','negação'],10), (['elevação','ações operacionais globais'],14),
+ (['solicitar perfil','comprovativos','pedido de perfil'],3), (['mfa','multifator','sessões'],24),
+ (['arquivo','exclusão','restauro'],32), (['auditor','exporta'],13), (['auditoria','rastreabilidade'],23),
+ (['organização','representação','propriedade'],6), (['tipos de oportunidade','tipo autorizado'],7),
+ (['aprovação','validar','validador','correções'],11), (['publicador','publicar','publicação'],12),
+ (['estados','rascunho','submiss'],8), (['menu','navegação','dashboard'],5), (['público','favoritos','alertas'],2)]:
+ if any(term in value for term in terms): return requirement
+ return 1
+
+assigned = collections.defaultdict(list)
+v1_exact = {text: classify(number, text) for number, text in sources[0]['paragraphs'] if text}
+for source in sources:
+ for number, text in source['paragraphs']:
+ requirement = classify(number, text) if source['prefix'] == 'PROFILEV1' else v1_exact.get(text, classify(0, text))
+ assigned[requirement].append({'id': f"{source['prefix']}-P{number:04d}", 'pedido': text,
+ 'fontes': [f"{source['name']} | parágrafo {number} | SHA256 {source['sha256']}"],
+ 'aceitacao': definition[requirement]['acceptance'], 'estado': definition[requirement]['state'],
+ 'variantes': 'Versão1.0 ou exemplar anterior preservados integralmente; divergências em perfis-v1-reconciliacao.md.', 'modulo': 'perfis e oportunidades'})
+
+existing = {r['ID']: r for r in rows}
+for n, data in definition.items():
+ identifier = f'AUD-PROFILE-{n:02d}'
+ references = assigned[n]
+ # Some requirements are direct reconciliation decisions, without a dedicated paragraph.
+ if not references:
+ references = [{'id': identifier + '-USER-20261010', 'pedido': data['title'], 'fontes': ['Pedido direto do responsável10/10/2026 nesta conversa'],
+ 'aceitacao': data['acceptance'], 'estado': data['state'], 'variantes': 'Reconciliação funcional com v1 e auditoria existente.', 'modulo': 'perfis e oportunidades'}]
+ row = {field: '' for field in fields}
+ row.update({'ID': identifier, 'Pedido/trecho': data['title'], 'Fonte/ocorrências': '\n'.join(ref['fontes'][0] for ref in references),
+ 'Módulo': 'perfis e oportunidades', 'Rotas': '/dashboard; /perfil/promotor; /minhas-oportunidades; /perfis/gestao; /perfis/auditoria; /perfis/*',
+ 'Implementação encontrada': data['implementation'], 'Disponibilidade ativa': 'Leitura10/10: instalação040000ausente; PORTAL_PROFILE_ACCESS_ENABLED=false; nenhuma conta ativa alterada. QA18097: schema instalado e flagtrue.',
+ 'Evidência funcional': data['evidence'] + ' | Evidências privadas sanitizadas: profiles-v1-http-qa.json; profiles-v1-recovery-audit-qa.json; profiles-v1-final-qa.xml; profiles-v1-current-version-qa.json quando disponível.',
+ 'Estado': data['state'], 'Lacuna': data['gap'], 'Dependência': 'Reutilizar entidades existentes; QA isolada; aceitação visual pendente. Dependências concretas descritas no critério/lacuna, sem bloquear trabalho independente.',
+ 'Critério de aceitação': data['acceptance'], 'Prioridade': 'P0' if n in {16,17,24} else 'P1',
+ 'Versões divergentes': 'Exemplar anterior e v1 preservados. Administração integral anterior passa a controlada na v1; edição organizacional aprovada nesta conversa; Promotor solicita arquivo; gestores legados não se tornam Superutilizadores. p337/p355/SU04/SU05/GOV01 acrescentam governança/atomicidade.',
+ 'IDs das linhas de origem': ';'.join(ref['id'] for ref in references), 'Quantidade de linhas de origem': str(len(references)),
+ 'Critérios e versões por origem (JSON)': json.dumps(references, ensure_ascii=False, separators=(',', ':')),
+ 'Interface': 'Preparada em QA, sem demonstração visual. C37 e A/B mantidos pendentes.' if n != 27 else 'Não aplicável: decisão documental restrita, sem substituição de autenticação.',
+ 'API': data['evidence'], 'Gravação': 'QA: entities canónicas/papéis/pedidos/workflow/audit_events; gravações sintéticas somente. Não inferir persistência dos fluxos descritos como pendentes.',
+ 'Recuperação': 'Pedidos e rascunho15 recuperados em novas sessõesMFA; auditoria/revogação/dupla comprovadas nos escopos descritos. Outros critérios pendentes não fechados.',
+ 'Resultado apresentado': 'Props/JSON/mensagens de autorização verificados; resultado renderizado no navegador pendente.' if n != 27 else 'Fortify mantido; não há integraçãoKeycloak instalada/declarada.',
+ 'Consolidação': 'Mesmo CSV canónico.32requisitos funcionais novos; parágrafos de fontes preservados como ocorrências, incluindo estrutura/tabelas/casos, sem os contar como requisitos independentes.'})
+ if identifier in existing:
+ existing[identifier].update(row)
+ else:
+ rows.append(row)
+
+marker = '[Perfis v1 QA10/10/2026]'
+for identifier in ['AUD-OP-01', 'AUD-OP-02', 'AUD-OP-03', 'AUD-OP-04', 'AUD-DASH-01', 'AUD-UI-01', 'AUD-OPS-01']:
+ row = existing.get(identifier)
+ if not row: continue
+ for field, text in {'Implementação encontrada': 'Reutilização/permissões organizacionais e workflow parcial nos AUD-PROFILE-01–32; nenhum sistema paralelo de identidades.',
+ 'Evidência funcional': 'Dashboard→novo draft15→recuperaçãoMFA→coedição21/22 HTTP; tipos/org/multirrole403; requestArchive persiste. Submissão422 por contrato completo ausente. VisualC37/C43/A-B pendente.',
+ 'Lacuna': 'Critérios específicos preservados; não confundir workflow parcial/props de menu com submissão/aprovação/publicação completas ou demonstração visual.'}.items():
+ if marker not in row[field]: row[field] += ' | ' + marker + ' ' + text
+ if identifier == 'AUD-OP-03': row['Estado'] = 'parcial'
+ if identifier == 'AUD-OP-03':
+ for field, text in {
+ 'Interface': 'Navegação/pedido de arquivo preparados; revisão visual e formulário especializado completos pendentes.',
+ 'API': 'Workflow parcial v1 com autorização/razão/etag; submit real422 por contrato incompleto. Revisão/correção positiva apenas em fixture explicitamente submetida; não é submissão integral.',
+ 'Gravação': 'QA: owner/org/contributors, pedido de arquivo, versões/transições parciais e audit_events preservados; zero decisões/publicações ativas.',
+ 'Recuperação': 'Novo rascunho15 e contexto recuperados em nova sessãoMFA; fixture verifica revisão/correção. Ciclo integral publicado ainda ausente.',
+ 'Resultado apresentado': 'Estado corrente parcial; props/mensagens API comprovadas, interface e aprovação/publicação reais pendentes. Registos de não implementação anteriores são históricos.'
+ }.items():
+ if marker not in row[field]: row[field] += ' | ' + marker + ' ' + text
+for identifier in ['AUD-GEO-02', 'AUD-GEO-03']:
+ row = existing[identifier]
+ field = 'Evidência funcional'
+ if marker not in row[field]:
+ row[field] += ' | ' + marker + ' ConsumidorPromotor autorizado:11províncias, CaboDelgado selecionada/guardada/recuperada noutra sessão e1área geométricaAPI. Novo endpoint reutiliza catálogo/serviço; não demonstra mapa renderizado nem resolve31distritos/157postos pendentes. QA393privadas,ativo0; publicação separada.'
+
+# Before-source entries must be byte-equivalent in meaning; state/evidence reconciliation cannot rewrite them.
+for old in before:
+ current = next(r for r in rows if r['ID'] == old['ID'])
+ for key in ['IDs das linhas de origem', 'Quantidade de linhas de origem', 'Critérios e versões por origem (JSON)', 'Pedido/trecho', 'Critério de aceitação', 'Versões divergentes']:
+ assert current[key] == old[key], (old['ID'], key)
+assert len(rows) == len({r['ID'] for r in rows}) == 3386
+all_references = [item for row in rows for item in json.loads(row['Critérios e versões por origem (JSON)'])]
+profile_refs = [item for item in all_references if item['id'].startswith(('PROFILEV1-', 'PROFILEOLD-'))]
+assert len(profile_refs) == len({r['id'] for r in profile_refs}) == 1001
+with MATRIX.open('w', encoding='utf-8-sig', newline='') as handle:
+ writer = csv.DictWriter(handle, fieldnames=fields); writer.writeheader(); writer.writerows(rows)
+states = collections.defaultdict(lambda: {'requisitos': 0, 'linhas_origem': 0})
+for row in rows:
+ states[row['Estado']]['requisitos'] += 1
+ states[row['Estado']]['linhas_origem'] += int(row['Quantidade de linhas de origem'])
+source_hash = hashlib.sha256(json.dumps(all_references, ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode()).hexdigest()
+counts = {'requisitos': len(rows), 'linhas_matriz': len(rows), 'linhas_origem': len(all_references), 'por_estado': dict(states),
+ 'conservation_sha256': source_hash, 'before_source_occurrences_preserved': 5830, 'new_document_paragraph_references': 1001,
+ 'new_direct_user_references': len(all_references)-5830-1001,
+ 'metodo': 'Mesma matriz;3354pedidos existentes e suas5830referências preservados,32requisitos verificáveis de perfis. Parágrafos estruturais são referências, não pedidos independentes. AUD-OP-03 passa a parcial pelo incremento, sem fechar workflow.',
+ 'browser_current_version_verified': False}
+(PRIVATE / 'contagens-requisitos.json').write_text(json.dumps(counts, ensure_ascii=False, indent=2), encoding='utf-8')
+proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'all_previous_ids_preserved': True, 'previous_source_references_preserved': True,
+ 'sources': [{k:v for k,v in source.items() if k != 'paragraphs'} for source in sources], 'accessible_corpus_files': len(paths),
+ 'inventory_entries': len(inventory), 'inventory_entries_added_this_pass': len(new_inventory), 'inventory_added_relative_prior586': len(inventory)-586,
+ 'office_lock_markers_inventoried_by_bytes': sum(Path(p).name.startswith('~$') for p in paths), 'inventory_unreadable': errors,
+ 'matrix': counts, 'qa_only_implementation': True, 'active_writes': 0}
+(PRIVATE / 'profiles-v1-reconciliation-proof.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({k:v for k,v in proof.items() if k not in {'sources','matrix'}},ensure_ascii=False))
+print(json.dumps(counts,ensure_ascii=False))
+
+# Preserve later workflow evidence when rebuilding the original profile reconciliation.
+if (PRIVATE / 'opportunity-workflow-http-qa.json').exists():
+ import runpy
+ runpy.run_path(str(ROOT / 'tools/portal-audit-workflow-update.py'), run_name='__main__')
diff --git a/tools/portal-audit-semantic-docs.py b/tools/portal-audit-semantic-docs.py
new file mode 100644
index 00000000..90bebaa6
--- /dev/null
+++ b/tools/portal-audit-semantic-docs.py
@@ -0,0 +1,173 @@
+"""Update the existing executive report, backlog and evidence; retain earlier versions as history."""
+import collections
+import csv
+import json
+import re
+import sys
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
+sys.stdout.reconfigure(encoding='utf-8')
+csv.field_size_limit(16 * 1024 * 1024)
+http = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text(encoding='utf-8-sig'))
+editorial = json.loads((PRIVATE / 'opportunity-semantic-publication-http-qa.json').read_text(encoding='utf-8-sig'))
+verified = json.loads((PRIVATE / 'opportunity-semantic-verification-qa.json').read_text(encoding='utf-8-sig'))
+environment = json.loads((PRIVATE / 'opportunity-semantic-environment-qa.json').read_text(encoding='utf-8-sig'))
+active = json.loads((PRIVATE / 'dashboard-active-readonly.json').read_text(encoding='utf-8-sig'))
+preserved = json.loads((PRIVATE / 'profiles-v1-preservation-qa.json').read_text(encoding='utf-8-sig'))
+counts = json.loads((PRIVATE / 'contagens-requisitos.json').read_text(encoding='utf-8-sig'))
+assert http['result'] == editorial['result'] == 'passed'
+assert http['target'] == 'desk_restore_20261009_174726_test:55441'
+assert all(p['active_writes'] == 0 for p in [http, editorial, verified, environment, active, preserved])
+documents_path = PRIVATE / 'opportunity-semantic-documents-http-qa.json'
+document = json.loads(documents_path.read_text(encoding='utf-8-sig')) if documents_path.exists() else {}
+names = {'investment_project': 'Investimento', 'real_estate': 'Imobiliário', 'land_rights': 'Fundiário/DUAT',
+ 'business_sale': 'Venda de negócio', 'business_partnership': 'Parceria de negócio', 'franchise': 'Franquia',
+ 'concession': 'Concessão', 'financing': 'Financiamento', 'supply': 'Fornecimento', 'other': 'Outros'}
+category_rows = []
+for case in http['cases']:
+ category = case['category']
+ publication = ('Pública, só teaser; prova editorial posterior' if category == 'business_sale' else
+ 'Bloqueada: autorização externa pendente' if category == 'land_rights' else
+ 'Interna; sem exposição pública' if case['publication'] == 'published-internal' else 'Bloqueada')
+ ready = case['submission'] == 'passed'
+ category_rows.append(f"| {names[category]} — #{case['id']} | Incompleto guardado e recuperado | Edição gravada, nova sessão MFA | {'Aceite' if ready else '422: perfil modular por aprovar'} | {'Gates e aprovação interna' if ready else 'Não elegível'} | {publication} |")
+category_table = '\n'.join(category_rows)
+state_table = '\n'.join(f"| {state} | {v['requisitos']} | {v['linhas_origem']} |" for state, v in counts['por_estado'].items())
+pdf_evidence = ('PDF válido de uma página, parser estrito, upload/scan ClamD real e SHA; download 21/24/25, negação 23(403); exclusão lógica→download404/opção removida; restauração→nova sessão→bytes/hash idênticos. Prova `opportunity-semantic-documents-http-qa.json`.'
+ if document.get('result') == 'passed' else 'Ensaio PDF web18097 ainda não encerrado; consultar a prova sanitizada da operação, sem extrapolar PNG a outros tipos.')
+summary = f'''## Resultado atual por categoria — semântica e atribuições em QA, 10/10/2026
+
+Este bloco é a evidência mais recente desta matriz; as secções anteriores abaixo permanecem como histórico. Estados antigos sobre objetos opacos, coordenação editorial e ausência de 190000 ficam confrontados com os resultados concretos deste bloco. **Código preparado e HTTP/persistência em QA não encerram interface nem funcionalidade ativa.** Não houve escrita na base ativa. C37 e aceitação visual permanecem pendentes.
+
+Servidor **http://127.0.0.1:18097**, base **desk_restore_20261009_174726_test:55441**, Fortify e MFA normais. **Promotor QA 21** continua a conta de ensaio do dashboard. Não usar Auditor ou Superutilizador em seu lugar.
+
+| Categoria / ID QA | Rascunho | Edição / recuperação | Submissão | Revisão | Publicação |
+| --- | --- | --- | --- | --- | --- |
+{category_table}
+
+As dez categorias recuperaram dados noutra sessão autenticada. As seis com contrato definido aceitaram os cenários semânticos documentados; as quatro restantes conservaram rascunhos, sem inventar um perfil modular para as submeter. Fundiário #32 separa aprovação interna da decisão externa. Venda #33 passou depois pelo percurso editorial público, sem divulgar resumo/dados privados.
+
+**Campos e regras preparados:** cronograma com início/fim/responsável e dependências acíclicas; maturidade com os oito códigos normativos; viabilidade com cenário/indicadores/modelo e estudo, sem score de sucesso; serviços/título/entidade emissora/ocupação/avaliação imobiliários; parcelas com editor de vértices/anéis MultiPolygon, benfeitorias e consulta comunitária; constituição/beneficiário efetivo, exercícios existentes, ativos/passivos, obrigações laborais, licenças, NDA, governação e franquia. O contrato é elaborado no servidor e consumido pelo editor, sem templates JSON divergentes no cliente. Objetos legados conservam chaves anteriores. O schema original de 110 definições mantém SHA `{verified['source_schema_sha256']}`.
+
+**Falhas corrigidas com prova:** {len(http['negative_fields'])} recusas 422 identificaram o campo e conservaram o rascunho inválido: fim anterior ao início, ciclo, falta de cenário/modelo, serviços incompletos, título de outra oportunidade, comunidades sem consulta, financeiros insuficientes e contingências não declaradas. Erros `canonical.` são devolvidos pela API e ligados aos controlos; a posição/clareza visual ainda não foi observada. O formulário núcleo duplicado foi retirado do modo perfil; gestão legada mantém o seu acesso próprio.
+
+**Filas e perfis:** revisão, preparação editorial, recurso e tarefas atribuídas reutilizam `tasks`, com ligação explícita ao bigint da oportunidade. #30 pediu parecer a 29: o destinatário errado recebeu403, a aprovação com parecer pendente422; a resposta foi guardada e concluiu a tarefa, sem aprovar o gate automaticamente. #33: coordenador editorial25 atribuiu a29; tarefa recuperada na fila; outro Publicador403; o designado publicou. Papéis/âmbitos/independência/responsabilidades são verificados no servidor; revogação após aprovação bloqueia publicação no teste específico. Responsabilidades atribuídas neste ensaio são sintéticas, sem competência institucional real inferida. SLA permanece `unconfigured` e `due_at=null`.
+
+**Consumidores territoriais/documentais:** seis contratos recuperaram país MZ e uma localização com limite disponível; API retornou dois limites de contexto. O editor e os campos `location_id` consultam o território mais profundo e mantêm a parcela separada do limite administrativo. País FR do mercado do investimento foi gravado/recuperado; isto não encerra origem/filtros/estatísticas de todos os formulários. Originais dos seis casos permitiram21/24/25 e negaram organização estrangeira23(403). O download/prévia reutiliza `VerifiedDocumentBinary`, que verifica cifra/hash/scan e controla falhas; não altera os originais. #33 recuperou original da imagem e duas derivadas limpas pelo ClamD real. {pdf_evidence}
+
+**Limites concretos:** correspondência entre titular/documento/cadastro e âmbito urbanístico exige evidência e decisão do gate, sem inferir autenticidade jurídica pela existência de um UUID. Limites urbanísticos e materialidade não são inventados. Unidades aplicáveis, Response integral e relações do §27 ainda precisam de reconciliação. O schema original exige pelo menos um exercício financeiro; casos com zero exercícios devem ter regra expressa reconciliada antes de serem declarados cobertos. A moeda obedece ao padrão do contrato; não existe aqui prova de catálogo completo ISO4217. DOCX/XLSX, partilhas e PDFs/exportações/derivadas sem prova específica continuam abertos. C37, A/B e todo o percurso visual por perfil permanecem pendentes.
+
+**Preservação e compilação:** 18 conjuntos de linhas anteriores por ID/colunas originais preservados; MFA18 intacto. Manifesto ativo `{verified['active_manifest_sha256']}` preservado. Manifesto QA `{verified['qa_manifest_sha256']}`; bundle próprio `build-qa-opportunities`, sem recompilar o ativo. TypeScript, PHPStan e testes específicos passaram; as contagens de testes não são usadas como critério de conclusão.
+
+Mesma matriz: **3.386 requisitos / 3.386 linhas**, **6.838 ocorrências de origem**. IDs, fontes, critérios, versões divergentes e referências anteriores conservados.
+
+| Estado canónico | Requisitos | Ocorrências de origem |
+| --- | ---: | ---: |
+{state_table}
+
+Linhas principais: **AUD-OP-02/03/04, AUD-GEO-03, AUD-PROFILE-11/12/19/25/28/31 e AUD-OPS-01**, em [matriz-requisitos.csv](matriz-requisitos.csv). Nenhum desses critérios visuais foi fechado por API.
+'''
+
+backlog = '''## Próximo trabalho executável e decisões separadas — lote semântico atual
+
+| Prioridade / requisito | O que já tem prova QA | Falta / próxima ação e critério concreto |
+| --- | --- | --- |
+| P0 — UI-01/C37 | Diagnóstico/MFA preservados; ensaios HTTP21 não fecham18. | C37 e confirmação visual continuam pendentes conforme pedido. Quando retomados, dashboard→MFA→sessão→refresh→logout→novo login; rastreio sanitizado e primeiro ponto de perda. Nenhum novo teste visual solicitado agora. |
+| P1 — OP-04 / PROFILE-28/25 | Seis editores/regras no contrato do servidor; dez drafts e doze rejeições por campo recuperadas. | Observar cada categoria na UI21, erro junto ao controlo e nova sessão; reconciliar unidades aplicáveis, entidade/título/cadastro e limites urbanísticos com gates; completar Response/§27 apenas reutilizando entidades. Não regredir source/enums/IDs ou tornar campos incompletos obrigatórios para guardar. |
+| P1 — OP-03 / PROFILE-11/12/19 | Filas, parecer atribuído, resposta, revisão e coordenação editorial com task/hash/papéis; negações específicas. | Interface por24/25/29, reatribuição e revogação; incidentes, disponibilidade e revisão periódica. Parecer externo requer responsabilidade institucional concreta, não um ator fictício; aprovação interna não substitui decisão externa. |
+| P1 — GEO-03 / COUNTRY/STATS | Seis contratos ligam localização/documentos por IDs e país MZ; investimento recupera mercadoFR; editores consultam geometrias no nível selecionado. | Verificar visual de todos os consumidores afetados, país/origem→recuperação→filtro→estatística por formulário. Resolver nomes pendentes do pacote:31distritos+157postos; localidades/parcelas não inferidas de limites administrativos. Reutilizar importação autenticada/idempotente; publicação de camada é separada. |
+| P1 — OP-02 / LIB / PROFILE-23 | Originais por perfil, negação de organização23, cifragem/hash, PNG e duas derivadas ClamD; PDF do ensaio atual separado. | Continuar DOCX/XLSX, partilhas, PDFs/exportações/derivadas sem prova específica; preservar originals/versões. Consistência de erro404 recurso excluído versus423 scan pendente foi corrigida no consumidor de oportunidades. |
+| P1 — PROFILE-23 | Dois avisos preexistentes de league/commonmark identificados no lote anterior. | Avaliar consumidores e corrigir compatibilidade emQA; não apagar o achado nem atribuir a Opis. |
+| P2 — PROFILE-31 / OPS-01 | 190000confirmadaQA/ausenteativo;030/040QA;baseBalcãoativa instalada, hashes atualizados. | Construir instalação/bootstrap autenticados040 com duasidentidades reais explicitamente designadas; não mudar titulares nem retirar privilégio ativo automaticamente. Apósvisual, fixar candidata e renovarbackup/restauro dessa revisão; executar apenas migrações faltantes pelo mecanismo adequado. |
+
+Decisões independentes, sem bloquear este lote:
+
+1. **Concessão, financiamento, fornecimento e outros:** quais versões imutáveis de perfil modular, campos obrigatórios, documentos e gates são aprovadas para cada categoria? Sem esse contrato, guardar/editar funciona; submissão/revisão/publicação continuam bloqueadas.
+2. **SLA:** qual política versionada fixa prazo por tipo de tarefa, tolerância, número de ciclos e escalamento? Quem assume formalmente cada competência de coordenação, parecer técnico/jurídico, publicação e recurso? Manter prazo nulo e atribuição explícita até existir decisão; não usar nomes/prazos de QA como norma.
+3. **Condições sem regra inequívoca:** qual âmbito/citação estabelece a aplicabilidade de unidades/limites urbanísticos e materialidade? Como reconciliar o mínimo de um exercício do schema com entidades sem exercícios existentes? Não substituir valores ausentes por zero nem alterar silenciosamente a versão aceita.
+
+Não iniciar jornadas educativas novas. Mantêm-se cinco fases/19 etapas e URLs, dossier privado, oportunidade publicada, fontes oficiais aceites e histórico.
+'''
+
+activation = f'''## Ativação reconciliada: 030000, 040000 e **09/190000** — nenhuma execução no ativo
+
+A omissão de **2026_10_09_190000_prepare_investor_path** na sequência anterior foi um erro documental; a extensão **continua necessária e não foi substituída**. Não confundir com **2026_10_07_190000_create_internal_virtual_desk**, que já está instalada no ativo.
+
+| Recurso | QA restaurada:55441 | Ativo investemoz:5432, READ ONLY | Evidência |
+| --- | --- | --- | --- |
+| Gestão020000 | Instalada | Instalada | Ledger/schema anteriores preservados |
+| Balcão07/190000 e orientação08/120000 | Instalados | Ambos no ledger | Leitura efetiva das migrações, sem boot de sessão ativa |
+| Recursos09/030000 | Instalada | Ausente | Tabelas e ledger; não repetirQA |
+| Perfis10/040000 | Instalada | Ausente | Tabelas/verificaçãoQA; nunca instalada no ativo neste trabalho |
+| Percurso09/190000 | **Ledger + duas colunas + definição publicada** | **Ledger ausente; duas colunas ausentes; nenhuma definição** | `dashboard-active-readonly.json`, `opportunity-semantic-environment-qa.json` |
+
+DefiniçãoQA `61000919-0000-4000-8000-000000000001`, publicada, SHA256 **{environment['definitions'][0]['sha256']}**. Duas colunas: `investor_journeys.path_definition_id` e `journey_steps.path_detail`. Mantém cinco fases e rastreabilidade das19etapas; não renumera/reescreve os roteiros existentes. Recurso preparado/definição publicada não demonstra A/B na interface.
+
+Dependências verificadas no código: **030000** usa oportunidades/documentos existentes e cria três coleções de recursos; **040000** acrescenta quatro tabelas de autorização/auditoria, uma coluna de revisão em users e três colunas em opportunities, preservando identidades/histórico; não usa as colunas de190000. **190000** usa investor_journeys/journey_steps/questionnaire_versions e depende da baseBalcão/orientação incluída no instalador. Não existe dependência DDL entre030/040 e190; disponibilizar o workflow requer020+030+040 e tasks/catalogue existentes; disponibilizar o percurso integrado requer190 e as capacidades instaladas/configuradas. Os fingerprints incluem código comum de perfis: alterar o código invalida provas antigas de readiness, sem converter isso numa dependência de schema.
+
+| Ordem futura | Ação concreta e efeito / contagem esperada | Dependência e reversão |
+| --- | --- | --- |
+| 0 | Incorporar visualC37/Promotor21/A-B; corrigir falhas e fixar revisão/manifesta/configuração. Renovar dumpDB+ficheirosoriginaisprivados+chaveestável e restauroverificado numa novaQA. | Candidata ainda não fixada; provas antigas não são backup dessa revisão. Nunca key:generate indiscriminado. |
+| 1 | Disponibilizar código/Composer/bundle após aprovação de ativação, flagsfalse. | Nesta análise só buildQA foi atualizado; manifestativo preservado. Reversão para código/build anteriores e flagsfalse; assegurar compatibilidade de leitura. |
+| 2 | **030000**, se ledger/schema realmente ausentes: préviaGET e aplicaçãoPOST autenticada `/management/opportunity-resources-install` com hash/confirm. | Três coleções resource e metadado de cifra; **zero documentos/dados publicados/importados**. Base020/documentos existentes. Downgrade destructive recusado se originais cifrados usados. |
+| 3 | **040000**, se ausente: instalar quatro tabelas/colunas através de mecanismo autenticado e bootstrap/recuperação da dupla, ainda por implementar paraativo. | Não substituir por migrateglobal/configmanual para contornar guarda. **Zero contas/grants QA** noativo. Titulares/reconciliação de permissões reais precisam de decisão explícita. Código independente de190. |
+| 4 | **09/190000**, se ausente: préviaGET e aplicaçãoPOST autenticada `/management/balcao-install`; instalador seleciona só migrações faltantes. | BaseBalcão07/190000 e orientação08/120000 jáconstamdoativo: não repetir. **Duas colunas + uma definição publicada**, se não existir equivalente; **zero dossiers/journeys criados automaticamente**. Versões publicadas imutáveis. |
+| 5 | Configurar catálogos/responsabilidades reais e instalar apenas contratos modulares aprovados; comparar IDs/citações/versões. | A autoridade sintética QA3e1ff315… e atores21–31 não são dados deativação. Sem alteração automática de valores legados. |
+| 6 | Importação cartográfica autenticada privada `/management/territory-geometry-import`: prévia/correspondências/hash→aplicação idempotente→auditoria. | QA393=11províncias+128distritos+254postos; ativo0naúltimaleitura. **393 candidatas inequívocas**, sujeitas à prévia da revisão e aos mesmos IDs;188pendentes(31/157), sem criar geometrias falsas. Contagem final deve ser medida no alvo. Reversão por lote/metadados e histórico, sem apagar cadastros. |
+| 7 | Ativar flags de perfis/oportunidades e percurso separadamente, testar navegação completa e permissões. | 030/040 antesdoscontratos/workflow;190antesdodisponibilizarpercurso; C37/visual/A-B não encerrados. Preparação paralela e acesso direto continuam. |
+| 8 | **Publicar camadas, oportunidades ou documentos como ações separadas e explícitas**. | Nenhuma instalação/importação publica automaticamente; publicação não ativa cálculo fiscal. Usar decisões/evidências/hash atuais e autorização de divulgação. |
+
+Reversão: desativarflags/voltarbundle compatível e conservar originais/auditoria. Migrações usadas não devem ser eliminadas por rollback genérico;190recusadownquandohápercurso,030recusacomcifrados,040preservaperfil/oportunidade. Quando necessária reversão de dados, usar o restauroverificado da candidata com reconciliação das escritas posteriores. **ready=true é preparação; não instalação, ativação nem aceitação funcional.**
+'''
+
+cases = '''## Reprodução e evidências adicionais — mesmo inventário
+
+| Caso / requisito | Passos e esperado | Observado / causa | Correção e estado |
+| --- | --- | --- | --- |
+| C55 — OP-02 | QA21→PDF limpo→exclusão lógica→GETdownload. Esperado: recurso indisponível, sem atribuir falha de scan. Restaurar e recuperar original. | HTTP423/quarentena porque download juntava row inexistente à condição de scan. | Separa ausência/exclusão404 de quarentena423; teste específico e ensaioPDFweb18097. Originais/hash preservados; visualpendente. Prova da falha `opportunity-semantic-documents-http-qa-attempt1.json`. |
+| C56 — OP-04/PROFILE-25 | Promotor21 abre editor de categoria; campos de núcleo devem ter um único valor/controlo e erros associados. | Revisão do código: formulário legado e contrato canónico duplicavam título/território/campos, com valores independentes. | Contrato canónico único no modo perfil; formulário legado continua na gestão própria. BuildQA/TS e payloadAPI; observação visualpendente. |
+| C57 — OP-04/PROFILE-28 | Guardar fim anterior ao início/ciclo/serviços incompletos/documento estrangeiro/comunidade sem consulta/financeiros incompletos; recuperar noutra sessão; submeter. | Regras anteriores aceitavam objetos opacos sem semântica suficiente. | 12negativas422 com caminho de campo; rascunhos recuperados; seis cenários completos submetidos/revistos. Não extrapolar a regras jurídicas ainda sem âmbito/gate. |
+| C58 — OP-03/PROFILE-19/12 | Parecer com destinatário técnico/jurídico; responder outro ator; aprovar pendente. Depois atribuir publicação e tentar outro Publicador. | Fluxo anterior não tinha destinatário/resposta/fila completa nem atribuição editorial. | #30destinatário29/resposta/tarefa;outro403/aprovação422; #33filaeditorial29/outro25publica403/designado29publica. Sem gateautoaprovado/prazofictício; visualpendente. |
+| 190000 — OPS-01/PROFILE-31 | Comparar ledger/duascolunas/definição QA eativo, distinguir migraçãoBalcão07 depercurso09. | Plano anterior omitia recurso ainda ausenteativo. | 09/190000confirmadaQA e ausenteativo, necessária/nãosubstituída; seqüência autenticada recolocada. Nenhuma execuçãoativa. |
+'''
+
+manual = '''## Ensaio visual preparado — permanece pendente conforme pedido
+
+URL QA **http://127.0.0.1:18097/dashboard**. Conta **Promotor QA21**, MFA normal, credenciais/código obtidos apenas localmente. Não incluir cookies, cabeçalhos X-XSRF-TOKEN, segredos ou corpo do código em capturas. C37/conta18 é um ensaio independente e continua pendente.
+
+1. Entrar no dashboard como21. Esperado: **Minhas oportunidades** e **Nova oportunidade**, ambos funcionais, no contexto autorizado. URLlista `/minhas-oportunidades`; criação `/minhas-oportunidades/create`.
+2. Abrir cada ID QA30–39 em `/minhas-oportunidades//view` e, nos estados editáveis, `/edit`. Esperado: estado privado e publicação distintos; núcleo único, categoria correta e permissões aplicadas. #36–39devem continuar drafts.
+3. Criar rascunho incompleto, guardar; logout/nova sessãoMFA e recuperar. Não usar as fichas publicadas para substituir este passo. Esperado: mesmos dados/ID, sem mistura com outrosprojetos/oportunidades. Se ainda não houver localizações/documentos, guardar primeiro e abrir **Recursos**.
+4. Nos recursos `/minhas-oportunidades//resources`, selecionar país e hierarquia; conferir mensagem de território cadastrado, geometria selecionada disponível/ausente e mapa. A parcela declarada em DUAT deve manter geometria própria, sem substituir por limiteadministrativo. Conferir original/prévia antes/depois de recuperar.
+5. Num rascunho de ensaio das seis categorias, introduzir erro semântico e guardar; submeter. Esperado:422, mensagem junto ao campo, valores preservados; depois corrigir e resubmeter. Concessão/financiamento/fornecimento/outros devem informar perfilmodularpendente.
+6. Como24, abrir mesma ficha/fila (`/minhas-oportunidades?queue=review`), atribuir/iniciar→solicitarcorreção→21corrige→nova revisão/gates. Registar motivo e documentos da própria versão. Ensaiar parecer por destinatário29: outra resposta negada e tarefa/parecer recuperados sem gateautoaprovado.
+7. Como25, fila editorial (`?queue=publication`), designar Publicador independente; como29, fila `?queue=assigned`, comparar prévia/hash/teaser e publicar. OutroPublicadornãodesignado deve recebernegação; aprovarprópria/mesmaorganização/múltiplospapéis deve continuar negado. Não atribuirresponsabilidadesreais aos atoresQA.
+8. Depois de publicar, solicitar revisão/materialalteração; esperado: publicação anterior preservada até nova revisão. Fundiário32não pode contornar autorizaçãoexternapendente. Conferir suspensão e recuperação dos motivos/tarefas.
+
+Registar por ação URL/ator/ID/estado/API/persistência/resultado visível; associar a mesma matriz. A/B completos e cincofases/19etapas continuam no roteiro existente, sem renumerar. Não fechar critérios por leitura dos dados ou totaldetestes.
+'''
+
+marker = 'qa-semantic-20261010'
+
+
+def prepend(path, text):
+ existing = path.read_text(encoding='utf-8')
+ existing = re.sub(r'\n?.*?\n?', '', existing, flags=re.S)
+ parts = existing.split('\n', 1)
+ rest = parts[1].lstrip() if len(parts) > 1 else ''
+ path.write_text(parts[0] + '\n\n\n' + text.strip() + '\n\n\n' + rest, encoding='utf-8')
+
+
+for name, body in [('relatorio-executivo.md', summary), ('backlog.md', backlog), ('plano-ativacao.md', activation),
+ ('casos-reproducao.md', cases), ('roteiro-manual-perfis-v1.md', manual),
+ ('perfis-v1-reconciliacao.md', summary), ('cobertura-percursos-i0-i3.md', summary),
+ ('execucao-percurso-i1-i3.md', summary), ('workflow-oportunidades-qa.md', summary + '\n\n' + backlog + '\n\n' + activation + '\n\n' + cases + '\n\n' + manual)]:
+ prepend(DOCS / name, body)
+prepend(ROOT / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', manual + '\n\n' + summary)
+print(json.dumps({'updated_documents': 10, 'requirements': 3386, 'sources': 6838, 'visual_pending': True, 'active_writes': 0}))
+if (PRIVATE / 'profile-installation-http-qa.json').exists():
+ import subprocess
+ subprocess.run([sys.executable, str(ROOT / 'tools/portal-audit-installation-update.py')], check=True)
diff --git a/tools/portal-audit-semantic-update.py b/tools/portal-audit-semantic-update.py
new file mode 100644
index 00000000..dda0c950
--- /dev/null
+++ b/tools/portal-audit-semantic-update.py
@@ -0,0 +1,120 @@
+"""Reconcile current semantic evidence into the sole audit matrix, preserving every source and version."""
+import collections
+import csv
+import hashlib
+import json
+import re
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+MATRIX = ROOT / 'docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv'
+sys.stdout.reconfigure(encoding='utf-8')
+csv.field_size_limit(16 * 1024 * 1024)
+http = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text(encoding='utf-8-sig'))
+publication = json.loads((PRIVATE / 'opportunity-semantic-publication-http-qa.json').read_text(encoding='utf-8-sig'))
+verified = json.loads((PRIVATE / 'opportunity-semantic-verification-qa.json').read_text(encoding='utf-8-sig'))
+environment = json.loads((PRIVATE / 'opportunity-semantic-environment-qa.json').read_text(encoding='utf-8-sig'))
+active = json.loads((PRIVATE / 'dashboard-active-readonly.json').read_text(encoding='utf-8-sig'))
+assert all(p['active_writes'] == 0 for p in [http, publication, verified, environment, active])
+assert http['result'] == publication['result'] == 'passed'
+assert http['target'] == publication['target'] == 'desk_restore_20261009_174726_test:55441'
+assert sum(c['canonical_validation'] == 'passed' for c in verified['categories']) == 6
+rows = list(csv.DictReader(MATRIX.open(encoding='utf-8-sig', newline='')))
+before = {r['ID']: dict(r) for r in rows}
+assert len(rows) == len(before) == 3386
+baseline = PRIVATE / 'opportunity-semantic-matrix-before.csv'
+if not baseline.exists():
+ baseline.write_bytes(MATRIX.read_bytes())
+marker = '[Semântica QA 10/10/2026]'
+
+
+def append(row, field, value):
+ old = re.sub(re.escape(marker) + r'.*?(?= \| \[|$)', '', row[field]).strip(' |')
+ row[field] = old + ' | ' + marker + ' ' + value
+
+
+categories = '; '.join(f"{c['category']}#{c['id']}:{c['working_state']}" for c in verified['categories'])
+evidence = ('QA18097:10rascunhos incompletos/nova sessão FortifyMFA;6contratos semânticos submetidos e revistos com gates, '
+ '5publicações inicialmente internas/DUAT32aprovado internamente+publicação422poratoexternopendente;4rascunhos bloqueados '
+ 'por perfil modular não aprovado. 12erros422porcampo+rascunho inválido preservado. Estado atual:' + categories + '. '
+ 'Investimento30:parecer29atribuído/respondido,aprovadorpendente422/outrodestinatário403/gatesnãoautoaprovados. '
+ 'Venda33:coordenador25→publicador29/fila atribuída→outropublicador403→publicação pública sóteaser;privado preservado. '
+ 'Provas opportunity-semantic-http-qa.json, -publication-http-qa.json e -verification-qa.json; nenhum clique observado.')
+implementations = {
+ 'AUD-OP-03': 'Workflow existente reutilizado; filas revisão/editorial/recurso/atribuídas; parecer por gate/hash/destinatário independente; coordenação editorial/reatribuição explícita. Revalida gates e responsabilidades na publicação.',
+ 'AUD-OP-04': 'Adaptador semantic1 e OpportunityCategoryFields detalham os seis contratos do mesmo schema110defs: marcos/cenários, título/serviços/avaliação, comunidades/parcelas/benfeitorias e entidade/financeiros/governação/franquia/NDA/teaser. Fonte/hash/enums antigos preservados; não cria SQL ou identidades paralelos.',
+ 'AUD-OP-02': 'Referências documentais aninhadas pertencem à mesma oportunidade e constam do contrato; originais cifrados/hash/scan verificados. Download/prévia usam VerifiedDocumentBinary e erro controlado; recursos excluídos não são oferecidos no editor.',
+ 'AUD-GEO-03': 'Editor de parcela MultiPolygon com vértices/anéis/fecho explícito; limite administrativo separado. Seleção de localização e campos location_id usam nível mais profundo e mapa/contexto existente. API de seis consumidores recupera limite selecionado e dois limites de contexto; render pendente.',
+ 'AUD-PROFILE-11': 'Validador atribuído e gates por competência; parecer técnico/jurídico exige destinatário independente com âmbito/MFA, resposta exclusiva dele, motivo/evidência e tarefa existente. Parecer não substitui aprovação do gate.',
+ 'AUD-PROFILE-12': 'Publicação atribuível por publication_coordinator; assignee tem âmbito/MFA e é independente da autoria/aprovação. Publicador diverso403; prévia e projeção públicas do negócio usam apenas teaser autorizado.',
+ 'AUD-PROFILE-19': 'Filas por estado/recurso/assignee e nomes de participantes elegíveis no servidor; tasks existentes recebem pareceres/atribuições/revisões/editoriais. SLAunconfigured/due_atnull, sem prazos nem titulares reais inventados.',
+ 'AUD-PROFILE-25': 'Edidores declarativos detalhados pelo contrato do servidor, sem templates divergentes JS; erros canonical. junto aos controlos e acessibilidade; remoção do formulário núcleo duplicado no modo perfil. País/catálogo/autoridade/documentos selecionáveis; parcela/mapas reutilizados.',
+ 'AUD-PROFILE-28': 'Contratos existentes enriquecidos e versionados sem substituir fonte/artifact110defs; rascunho admite ausência/null e grava/recupera; submissão estrita. Seis categorias demonstradas semanticamente nos cenários documentados; quatro aguardam versões modulares aprovadas.',
+}
+gaps = {
+ 'AUD-OP-03': 'Visual integral/C37; incidentes/revisão periódica/agendamento; recurso e parecer externo institucionais/SLA versionado. Aprovação interna sintética não comprova atos externos.',
+ 'AUD-OP-04': 'Visual por categoria; correspondência documental/cadastral e urbanística exige evidência/gate humano; não compara automaticamente titular e teor do PDF. Aplicabilidade de unidades/limites/materialidade ainda não expressa por regra inequívoca; Response integral/§27 permanece aberto. Quatro perfis modulares sem decisão.',
+ 'AUD-OP-02': 'Visual de anexos/prévias; cobertura integral DOCX/XLSX/partilhas e PDFs derivados/exportações por perfil ainda sem prova web18097 específica. ClamD real por operação não extrapolado.',
+ 'AUD-GEO-03': 'Render/seletores e mapas visualmente pendentes;393geometriasprivadas=11províncias+128distritos+254postos,188correspondênciaspendentes=31distritos+157postos no pacote581. Localidades/geometrias de parcelas não inferidas desses limites. Nomes mantidos em correspondencias-cartograficas.md.',
+ 'AUD-PROFILE-11': 'Visual e responsabilidade institucional real; parecer externo/protocolos e disponibilidade completos. Gates sintéticos não são decisões jurídicas reais.',
+ 'AUD-PROFILE-12': 'Visual da prévia/imagem/mapa; agendamento/tradução/revisão periódica; DUAT comatoexternopendente não publicável; perfis/regras reais pendentes.',
+ 'AUD-PROFILE-19': 'Visual das filas e reatribuições; decisão exata:qual política versionada define prazos,tolerância,ciclos e escalamento? Quem detém as competências institucionais? Nenhum prazo/responsável real atribuído em QA.',
+ 'AUD-PROFILE-25': 'C37 e navegação/render/erros/seletores/ciclo por conta21 ainda pendentes; código e props não demonstram cliques. Preserva nova sessão e acesso direto às ferramentas.',
+ 'AUD-PROFILE-28': 'Quais versões imutáveis de perfil/campos/documentos/gates são aprovadas para concession,financing,supply,other? Sem inventar contratos. Visual e condições jurídicas/Response integral permanecem parciais.',
+}
+activation = ('Leitura ativaREADONLY10/10:020000eBalcão07/190000+08/120000instalados;030000não;040000não;'
+ '09/190000prepare_investor_pathausente(ledger/2colunas/definição). QA03/04/09-190instalados;'
+ 'definição19etapaspublicada61000919-0000-4000-8000-000000000001 SHAe0acbc723cd3def7e415b2ef7a0173add08387c3cedabac9bb7b86409e4d25bf. '
+ '09/190000nãofoi substituída:continuanecessária paraativo e não se repeteQA. 030/040semdependênciaDDL190;'
+ '190dependeBalcão/journeys/steps/questionnaire_versions;workflowusa020+030+040+tasks/catalogue. '
+ 'Planofuturo:visual/candidata→backup/restaurofrescos→códigoflagsfalse→030autenticada→040instalador/bootstrapautenticadosaindaemfalta→'
+ '190apenasfaltantesvia/management/balcao-install→dadosreais/perfis→cartografiaprivadaidempotente→flagspercurso/oportunidades→publicaçãoseparada. '
+ '0fixturesQAnoativo;readytrueépreparação;semativaçãoautorizada;reversãodesativaflags/preservahistóricoourestaurabackupverificado,nãodropusado.')
+for row in rows:
+ key = row['ID']
+ if key in implementations:
+ append(row, 'Implementação encontrada', implementations[key])
+ append(row, 'Evidência funcional', evidence)
+ append(row, 'Lacuna', gaps[key])
+ append(row, 'API', evidence)
+ append(row, 'Gravação', 'opportunities.management_draft/workflow_context, resources/documents, tasks/audit_events existentes; hashes e histórico. Apenas QA guardada.')
+ append(row, 'Recuperação', '10categorias/12rascunhos inválidos recuperados noutra sessão MFA; seisoriginais permitidos21/24/25 e negados23; parecer/fila/hash/pub separados da versão privada.')
+ append(row, 'Interface', 'Código/build exclusivosQA preparados; campo+erro, selector+mapa, filas/pareceres/atribuições. Nenhum clique ou render observado; C37/conta18 e aceitação visual/Promotor21 pendentes.')
+ append(row, 'Resultado apresentado', 'RespostaHTTP/JSON e persistência demonstrados pelos casos30–39; venda33pública por teaser na prova editorial posterior. Apresentação no navegador pendente.')
+ append(row, 'Disponibilidade ativa', 'Lote apenasQA18097;ativoREADONLY/flagsfalse,030000/040000/09-190000nãoinstaladas,0geometrias. Sem migração/importação/grants ativos.')
+ if key != 'AUD-OP-02':
+ row['Estado'] = 'parcial'
+ if key in ['AUD-OPS-01', 'AUD-PROFILE-31', 'AUD-DESK-01', 'AUD-GUIDE-01']:
+ append(row, 'Dependência', activation)
+ append(row, 'Evidência funcional', 'Provasdeledger/colunas/definição:dashboard-active-readonly.json e opportunity-semantic-environment-qa.json;preservação18coleções/MFA18/manifestoativo:profiles-v1-preservation-qa.json.')
+
+documents_path = PRIVATE / 'opportunity-semantic-documents-http-qa.json'
+if documents_path.exists():
+ doc = json.loads(documents_path.read_text(encoding='utf-8-sig'))
+ if doc.get('result') == 'passed':
+ row = next(r for r in rows if r['ID'] == 'AUD-OP-02')
+ append(row, 'Consolidação', 'PDFválido1pstrictparser+ClamDreal upload/sha/download21/24/25;23download/delete403;delete21download404/removeopçãoeditor;restore+novaMFA21bytes/hashidênticos. Provaopportunity-semantic-documents-http-qa.json. Sem DOCX/XLSX/partilhaderivadainferida.')
+
+protected = ['ID', 'Pedido/trecho', 'Fonte/ocorrências', 'Critério de aceitação', 'Versões divergentes', 'IDs das linhas de origem', 'Quantidade de linhas de origem', 'Critérios e versões por origem (JSON)']
+assert all(all(r[k] == before[r['ID']][k] for k in protected) for r in rows)
+with MATRIX.open('w', encoding='utf-8-sig', newline='') as handle:
+ writer = csv.DictWriter(handle, fieldnames=list(rows[0])); writer.writeheader(); writer.writerows(rows)
+origins = [i for r in rows for i in json.loads(r['Critérios e versões por origem (JSON)'])]
+assert len(origins) == 6838
+states = collections.defaultdict(lambda: {'requisitos': 0, 'linhas_origem': 0})
+for r in rows:
+ states[r['Estado']]['requisitos'] += 1
+ states[r['Estado']]['linhas_origem'] += int(r['Quantidade de linhas de origem'])
+counts_path = PRIVATE / 'contagens-requisitos.json'
+counts = json.loads(counts_path.read_text(encoding='utf-8-sig'))
+counts.update({'requisitos': len(rows), 'linhas_matriz': len(rows), 'linhas_origem': len(origins), 'por_estado': dict(states),
+ 'semantic_updated_at': datetime.now(timezone.utc).isoformat(), 'browser_current_version_verified': False,
+ 'conservation_sha256': hashlib.sha256(json.dumps(origins, ensure_ascii=False, sort_keys=True, separators=(',', ':')).encode()).hexdigest()})
+counts_path.write_text(json.dumps(counts, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'requirements': len(rows), 'source_occurrences': len(origins), 'updated': list(implementations), 'active_writes': 0}, ensure_ascii=False))
+if (PRIVATE / 'profile-installation-http-qa.json').exists():
+ import subprocess
+ subprocess.run([sys.executable, str(ROOT / 'tools/portal-audit-installation-update.py')], check=True)
diff --git a/tools/portal-audit-territory-coverage.php b/tools/portal-audit-territory-coverage.php
index f1db7878..f7760818 100644
--- a/tools/portal-audit-territory-coverage.php
+++ b/tools/portal-audit-territory-coverage.php
@@ -9,25 +9,15 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\RateLimiter;
$root = dirname(__DIR__);
-$proof = json_decode(file_get_contents($root.'/storage/app/private/investmoz-v2/opportunity-resources-backup-proof.json'), true, 512, JSON_THROW_ON_ERROR);
-$target = $proof['restored_target'];
-if (! ($proof['restore_verified'] ?? false) || ! preg_match('/^desk_restore_\d{8}_\d{6}_test$/D', $target['database']) || (int) $target['port'] !== 55441) {
- throw new RuntimeException('Verified restored QA target required');
-}
-foreach (['APP_ENV' => 'testing', 'APP_DEBUG' => 'false', 'APP_KEY' => 'base64:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',
- 'DB_CONNECTION' => 'pgsql', 'DB_HOST' => '127.0.0.1', 'DB_PORT' => '55441', 'DB_DATABASE' => $target['database'],
- 'DB_USERNAME' => 'postgres', 'DB_PASSWORD' => '', 'DB_URL' => '', 'CACHE_STORE' => 'array', 'SESSION_DRIVER' => 'array', 'QUEUE_CONNECTION' => 'sync'] as $key => $value) {
- putenv($key.'='.$value);
- $_ENV[$key] = $_SERVER[$key] = $value;
-}
+require_once $root.'/tools/portal-qa-environment.php';
+$target = portalQaEnvironment();
require $root.'/vendor/autoload.php';
$app = require $root.'/bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$kernel->bootstrap();
-$identity = DB::selectOne('SELECT current_database() AS database,inet_server_port() AS port');
-if ($identity->database !== $target['database'] || (int) $identity->port !== 55441) {
- throw new RuntimeException('Non-QA database rejected');
-}
+$identity = portalQaAssertTarget($target);
+DB::beginTransaction();
+DB::statement('SET TRANSACTION READ ONLY');
// Enumerating the whole catalogue is a QA coverage run, independent of rate-limit acceptance.
RateLimiter::for('api', fn () => Limit::none());
$expected = app(InvestmentGeography::class)->publicReferences()->whereIn('location_type', ['province', 'district', 'admin_post', 'locality'])
@@ -74,6 +64,7 @@ foreach (['province' => null, 'district' => 'province', 'admin_post' => 'distric
if (count($seen) !== $expected->count()) {
throw new RuntimeException('Unreachable catalogue references');
}
+DB::rollBack();
$result = ['captured_at' => gmdate('c'), 'target' => $identity, 'source' => 'Verified active backup restored in QA', 'counts' => $counts,
'references_expected' => $expected->count(), 'references_recovered' => count($seen), 'api_requests' => count($results), 'checks' => $results,
'visual_verified' => false, 'all_consumers_accepted' => false, 'geometry_rows' => DB::table('geo_geometries')->count(),
diff --git a/tools/portal-audit-update-independent.py b/tools/portal-audit-update-independent.py
new file mode 100644
index 00000000..f214392c
--- /dev/null
+++ b/tools/portal-audit-update-independent.py
@@ -0,0 +1,402 @@
+"""Reconcile an independent QA increment into the existing audit, preserving its sources."""
+import collections
+import csv
+import hashlib
+import json
+import re
+from datetime import datetime, timezone
+from pathlib import Path
+import xml.etree.ElementTree as ET
+
+root = Path(__file__).resolve().parent.parent
+docs = root / 'docs/investmoz/v2/auditoria-portal'
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+target = {'database': 'desk_restore_20261009_174726_test', 'port': 55441}
+marker = '[QA independente 10/10/2026] '
+
+
+def readable(text):
+ # Format this increment's prose only; retain every identifier/path/hash verbatim.
+ nouns = ('etapas', 'dossiers', 'limites', 'províncias', 'distritos', 'postos', 'originais', 'geo_locations',
+ 'novas', 'novos', 'privadas', 'públicos', 'públicas', 'referências', 'territórios', 'definições',
+ 'contratos', 'requisitos', 'linhas', 'ocorrências', 'lacunas', 'contextos', 'formulários',
+ 'tabelas', 'ficheiros', 'colunas', 'documentos', 'conversões', 'recursos', 'candidatos', 'nomes',
+ 'definição', 'níveis', 'versões', 'pendentes', 'instâncias', 'geometrias', 'já', 'elementos')
+ text = re.sub(r'\b([A-Za-zÀ-ú]+)(\d+)(?=(?:' + '|'.join(nouns) + r')\b)', r'\1 \2', text)
+ text = re.sub(r'(?'
+ end = ''
+ block = begin + '\n' + heading + '\n\n' + readable(body.strip()) + '\n' + end + '\n\n'
+ if begin in text:
+ start = text.index(begin)
+ finish = text.index(end, start) + len(end)
+ text = text[:start] + block + text[finish:].lstrip('\n')
+ else:
+ first = text.index('\n')
+ text = text[:first + 1] + '\n' + block + text[first + 1:].lstrip('\n')
+ path.write_text(text, encoding='utf-8')
+
+
+history_note = '**Versões anteriores preservadas:** as secções abaixo documentam os instantes anteriores.361 e2/39/179 são a baseline09/10; o estado cartográfico corrente deste lote é393 e0/31/157. Ready/hashes/contagens antigas não certificam esta revisão. C37 mantém a sua confirmação visual pendente, sem bloquear as frentes independentes.'
+state_table = '\n'.join(f"| {k} | {v['requisitos']} | {v['linhas_origem']} |" for k, v in counts['por_estado'].items())
+executive = f'''QA exclusiva: http://127.0.0.1:18097; alvo confirmado `{target['database']}:55441`. Testes de feature usam outra QA, `investmoz_test:55441`, com guarda antes de qualquer escrita. Sem alterações, instalação, importação ou publicação na base ativa. Cinco fases/19etapas preservadas;5dossiers/95etapas na QA web, sem criação de jornadas educativas.
+
+| Requisito | Entrega e prova | Critérios ainda abertos |
+| --- | --- | --- |
+| AUD-GEO-01/02/03; C38 | Correspondências explícitas Maputo Província, Maputo Cidade e Matola; descendentes por nome exato+pai. Ação autenticada/MFA no servidor18097 insere32limites internos:2províncias+8distritos+22postos.361originais e1990geo_locations preservados.32/32 novos recuperados via endpoint consumidor; público0/32.393/393 contextos por serviço;1920/1920referências territoriais por API. ProvinceSelect liga o nome guardado ao preview sem reescrever valores. |31distritos/157postos por nome; localidades sem polígonos neste exemplar; integração renderizada por consumidor e ato de divulgação separados. |
+| AUD-COUNTRY-01–04/06–07, STATS-01 | Provas renovadas por método/formulário: perfil/empresa/manifestação/público/quatro apoios/carteira/interesse público em negócio/wizard/fundiário/três Balcões/simulador/CRM. Gravação→GET→filtro→agregado quando aplicável; residência/constituição/fiscal/fundos distintos da origem declarada; unknown preservado. |Seleção, recibos, variações condicionais, filtros/tabela e nova sessão na interface. Não contar testes documentais selecionados pela palavra original como requisitos de países. |
+| AUD-LAND-01, PART-01, LIB-01/02, SCAN-01; C39/C40 |404 dos originais cifrados corrigido em fundiário e sala de parceria por VerifiedDocumentBinary comum; novos uploads registam tamanho/autor. PDF/PNG/JPEG com ClamD real, hash, quarentena/perfis/partilha/revogação/adulteração/recuperação. Lote documental QA privado, idempotente, sem substituir identidade conflituosa; actor sem permissão/ambiente ativo recusados. |Renderização PDF/impressão, ações visuais e restantes consumidores/tipos; lote ativo autenticado. Serviço ClamD real demonstrado separado de arranque/manutenção permanente/GD ativo. |
+| AUD-OP-02/SCAN-01; C41/C42 |PDFs sintéticos apenas com cabeçalho não provavam legibilidade: novos testes usam PDF válido de uma página, parseado independentemente. No servidor18097, novo PDF anexado à oportunidadeQA12→scan real→download→nova sessão→recuperação; outra conta403. Cinco binários anteriores preservados por SHA; PNG/3WebP recuperados, sem novo scan das derivadas. Credenciais fixas do script removidas; passwords/remember tokens de dois atoresQA auxiliares rodados; MFA/conta18 preservados. |PDF renderizado e interface documental pendentes. O placeholder anterior permanece conservado como evidência e não certifica abertura de PDF. |
+| AUD-OP-03/04 |Schema normativo §26 preparado e rastreável:110definições,9contratos Create/Patch/Response, sem renumerar IDs. |Workflow e validação/gates especializados continuam não implementados; nenhum fecho funcional atribuído ao artefacto. |
+| C37, AUD-UI-01, I1–I3 |Evidências anteriores conservadas, nenhum novo ensaio de login investidor neste lote. |Login/reload/logout/nova sessão e A/B completos na interface continuam pendentes. |
+
+| Nível INE2019 | Esperado no exemplar | Resolvido QA | Pendente |
+| --- | ---: | ---: | ---: |
+| Província |11|11|0|
+| Distrito |159|128|31|
+| Posto |411|254|157|
+| Total |581|393|188|
+
+Os denominadores da edição2019 não são os1920territórios do cadastro existente. [188lacunas por nome](correspondencias-cartograficas.md), incluindo Cidade De Maputo agregado e Mandie duplicado no próprio workbook; nenhuma equivalência por código/fuzzy, nem fusão de cadastros. Aceitação das fontes oficiais preservada.
+
+**Mesma matriz, sem requisitos amplos recém-fechados:**3354requisitos/3354linhas canónicas;5830ocorrências de origem. IDs, fontes, trechos, diferenças de versão, critérios e estados conservados.
+
+| Estado | Requisitos/linhas | Ocorrências |
+| --- | ---: | ---: |
+{state_table}
+
+Evidências privadas: `geometry-crosswalk-http-qa.json` (aplicação posterior22, além das2+8 anteriores registadas na auditoria), `geometry-crosswalk-preservation-qa.json` (total32novas), `geometry-crosswalk-consumers-http-qa.json` (HTTP32novas/0públicas), `geometry-consumers-path-qa.json` (serviço393), `territory-catalogue-coverage.json` (catálogo1920). Não confundir aplicação parcial inicial interrompida por Mandie com duplicação: as10já aplicadas foram reutilizadas na continuação; ambiguidade nominal fica pendente e não bloqueia outras correspondências únicas.
+
+Testes dirigidos: `geometry-crosswalk-qa.xml` (casos de vínculo/pai/exemplar/conflito/replay/reversão), `document-independent-qa.xml` (dois percursos PDF/PNG/JPEG/perfis), `document-batch-independent-qa.xml` (um caso ClamD real; dois de fixture), `countries-independent-qa.xml` e `countries-forms-independent-qa.xml` (métodos identificados na [cobertura](cobertura-percursos-i0-i3.md)). TypeScript/build/PHPStan dos componentes alterados passaram. A guarda de concorrência recusou um arranque paralelo de testes; ficou em `countries-forms-independent-lock-refusal-qa.xml`; o ensaio sequencial posterior passou. Isto é tooling protegido, não falha de formulário.
+
+Complemento documental: `document-types-fixture-qa.json`, `resource-originals-preservation-http-qa.json`, `resource-http-actors-rotation-qa.json` e nova versão de `resources-real-http-qa.json`; versão anterior arquivada antes da atualização. Credenciais novas somente no ficheiro privado local; nenhum cookie/OTP/body exportado. Não alterar os originais anteriores para tornar o ensaio verde.
+
+Código preparado e QA API/persistência demonstradas neste âmbito; interface não demonstrada. `candidate_revision_fixed=false`, `integrated_ui_ab_passed=false`, `activation_ready=false`. [Backlog atual](backlog.md) e [ordem de ativação/reversão](plano-ativacao.md). Não há candidata final nem novo backup final de ativação emitido.
+
+{history_note}'''
+insert('relatorio-executivo.md', '## Lote independente I0–I3 — 10/10/2026', executive)
+insert('execucao-percurso-i1-i3.md', '## Lote independente I0–I3 — 10/10/2026', executive)
+
+backlog = f'''Não aguardar C37 para executar os itens independentes. C37/P0 conserva a confirmação visual do login e cenáriosA/B; nenhuma nova tentativa solicitada neste lote.
+
+| Prioridade / requisito | Próxima correção executável e componentes | Dados/dependência concreta | Aceitação |
+| --- | --- | --- | --- |
+| P1 GEO-02/03; C38 |Resolver31distritos/157postos com crosswalk versionado por fonte/edição/pai; reutilizar geo_locations/geo_geometries, TerritoryGeometryImport/Preview/Fields/ProvinceSelect. Conferir todos os consumidores na lista existente. |Exemplar/linha que distingue Cidade De Maputo agregado e Mandie2linhas; restantes188nomes no relatório. Sem polígonos de localidade disponíveis no exemplar retido. Fonte aceite não exige nova certificação. |Prévia mostra origem/pai/candidato único; aplicar/replay0duplicados/GETresultado; mapa e campo guardar/reabrir/limpar descendentes respeitam perfil; sem divulgar limites privados automaticamente. |
+| P1 COUNTRY01–04/06–07, STATS01 |Verificar os seletores/validações condicionais ainda não demonstrados na interface, por formulário da cobertura; corrigir qualquer lacuna executável API/persistência adicional. Reutilizar249ISO, DeclaredOriginStatistics e payloads existentes. |Backend específico renovado; não inferir origem da residência/fiscal/fundos. Valores antigos sem origem ficam desconhecidos. |POST/GET/nova sessão/filtro/tabela/estado vazio próprios; ZZ422sem escrita, revisão409, outra conta403/404; conjuntos interests/desk/businesses separados. |
+| P0/P1 documental LAND01/PART01/LIB01–02/SCAN01; C39/C40 |Prosseguir restantes consumidores/tipos/perfis, renderização PDF/impressão e derivadas próprias; reutilizar VerifiedDocumentBinary, documents, scanner/jobs e auditoria. Implementar aplicação documental ativa autenticada antes de futura importação ativa; CLI permanece QA-only. |PDF/PNG/JPEG/fundiário/parceria e loteQA têm prova real; oportunidades PDF/PNG/3WebP e biblioteca/Balcão conservam provas anteriores. Arranque/reboot/assinaturas ClamD e GD PHPativo são pendências operacionais específicas. |Permissão antes dos bytes; scan do hash de cada original/derivada; original preservado; partilha/revogação recuperadas; incorreto/quarentena recusados; PDF efetivamente visível e impressão correta. Não generalizar prova de um consumidor. |
+| P1 OP03/04; C08 |Implementar adaptador do schema normativo110defs para OpportunityManagement/management_draft/version; validar Create/Patch por módulo antes de novas transições. Reutilizar OpportunityResources, serviços negócio/fundiário/documentos/territórios e audit_events. Em seguida revisão/devolução/aprovação/publicação com segregação autor/revisor/aprovador e versão aprovada. |Contratos9preparados; UUID de exemplo não renumera bigint. Estado fiscal/jurídico/decisão externa distintos de validação interna. Perfis adicionais exigem contrato aprovado da especificação, não campos inventados. |Rascunho incompleto permanece guardável; revisão precisa indica campo/regra/fonte; transição indevida403/422/409; alteração material invalida apenas aprovação da versão afetada; reviewer não se autoaprova; publicação separada; GET/auditoria/replay preservam IDs/história e permissões. |
+| P0 visual C37 + I1–I3 |Manter ensaio manualA/B existente em18097 com MFA sintético, sem credenciais na documentação. Incorporar cada resultado e corrigir falhas antes de fixar candidata. |Confirmar conta18 no MFA e recuperar novo cookie/session sem alterar chave nem conta13. Não bloqueia tarefas independentes acima. |A/B criação→gravação→nova sessão→aplicabilidade→ferramenta→resultado no dossier→Balcão→acompanhamento; tarefa paralela, ausência de mistura/acesso indevido;19etapas/5fases mantidas. |
+| P1 OPS01 |Após critérios visuais e correções, fixar revisão e renovar backup/restauro/compatibilidade; gerar provas verdadeiras para a ordem consolidada. |Ativo fora da autorização; confirmar ledger/contagens atuais por leitura futura, não repetir instalações. |Recursos030000/percurso190000/flag/importação1→2→3/publicação separados; reversão GIS3→2→1 preserva catálogo/originais/receipts e recusa descendentes/uso/publicação. |
+
+Concluído neste lote apenas o âmbito específico demonstrado por prova:32correspondências, recuperação documental cifrada e controlos do loteQA; nenhum requisito transversal inteiro encerrado. Workflow/contratos preparados documentalmente continuam não implementados funcionalmente. Cinco fases/19etapas e acesso direto a ferramentas preservados; nenhuma nova jornada educativa. [Matriz única](matriz-requisitos.csv), [evidências por consumidor](cobertura-percursos-i0-i3.md) e [plano](plano-ativacao.md).
+
+Complemento C41: novo PDF válido de1página já gravado/escaneado/recuperado no servidor18097, com5binários anteriores preservados. O placeholder antigo não é prova de renderização; no ensaio visual usar o novo recurso identificado em resources-real-http-qa.json, sem substituir/apagar o antigo. C42 retirou passwords fixas do script e rodou os dois atoresQA auxiliares; manter leitura das credenciais somente no ficheiro privado local, sem enviar na conversa. Não afeta conta18/MFA/C37.
+
+{history_note}'''
+insert('backlog.md', '## Backlog corrente do lote independente — 10/10/2026', backlog)
+
+activation = f'''Plano preparado para futura autorização; nenhuma ação ativa executada. Revisão não candidata: percurso `{runtime['code_hash']}`, cartografia `{runtime['geometry_code_hash']}`, recursos `{runtime['resource_code_hash']}`. `ready=true` antigo representa outra preparação e não instalação/conclusão.
+
+| Ordem | Ação futura | Dependência/efeito previsto | Reversão |
+| --- | --- | --- | --- |
+|0|Concluir critérios visuaisA/B, C37 e consumidores; corrigir falhas e fixar commit/assets/fingerprints.|Provas de API/persistência não substituem interface. Não há candidata final agora.|Corrigir/revalidar só critérios afetados; preservar provas anteriores.|
+|1|Renovar backup de DB+ficheiros privados/chaves/originais/metadados e restaurar em nova QA loopback*_test:55441.|Guarda antes da escrita; comparar schema/IDs/relações/hashes/classificações/RLS/ficheiros.288tabelas/5ficheiros são histórico09/10, não contagem a forçar. Provas de reversão/compatibilidade da candidata.|Nunca sobrescrever escritas posteriores sem reconciliação. Restauro ativo permanece fora desta autorização.|
+|2|Disponibilizar código/assets/configuração mantendo INVESTOR_PATH_ENABLED=false e TERRITORY_GEOMETRY_IMPORT_ENABLED=false.|Correções países/documentos/seletores não criam nem reclassificam dados por deploy. ClamD/GD somente nas operações binárias afetadas.|Rollback de código compatível preservando payloads novos/originais. CLI documents:import-batch --apply continua recusado no ativo.|
+|3|Gestor ativo autorizado: GET/POST /management/opportunity-resources-install **somente se030000ausente**.|Prévia/backup/hash/autorização atuais;3tabelas de associação+1coluna documents+função/3triggers;0documentos/recursos/geometrias criados automaticamente. Não repetir instalações básicas.|Down somente vazio; após uso preservar dados/originais e desligar disponibilização em vez de apagar.|
+|4|GET/POST /management/balcao-install somente para migrations pendentes, prevista190000.|2colunas+1definição imutável;0conversões/dossiers/etapas automáticas. Prova A/Bvisual atual exigida.19etapas/5fases e roteiros legados preservados.|Down recusa após uso; desabilitar flag mantendo definição/dossiers/história.|
+|5|Habilitar INVESTOR_PATH_ENABLED em ação separada, após schema e aceitação.|Mostra percurso;19etapas somente ao criar dossier novo; ferramentas diretas/URLs/IDs permanecem.|Flagfalse, sem apagar dossier/resultados/documentos/tarefas/consentimentos.|
+|6|Preparar prova específica cartográfica vinculada ao fingerprint/alvo/backuprestaurado/UI; habilitar rota separadamente; gestor/MFA GET /management/territory-geometry-import?level=1 → POST, depois2, depois3.|Cada prévia deve conservar exemplar/hash/scan/crosswalk/pai/conflitos. **Se ativo continuar0 e mesmas correspondências únicas:393=11+128+254 novas internas**,0geo_locations/locais/perímetros de investimento.31/157pendentes de fora. QA393inclui32novas e361preservadas; replay0novas. Scan vencido exige renovar prova por bytes, sem reabrir aceitação oficial.|POST /management/territory-geometry-import/{{batch}}/reverse com MFA/razão/idempotência; **postos→distritos→províncias**. Recusa descendentes ativos da edição mesmo sem FK, uso/alteração/publicação; só exclusão lógica de novos intactos não usados. Preservar reutilizados/catalogue/hash/histórico.|
+|7|Divulgar camadas por consumidor/âmbito autorizado em ação separada.|Importador não publica. Limites administrativos não são DUAT/perímetro do investimento; não transformar internal em public para passar ensaio. Mecanismo de divulgação de limites administrativos continua a concretizar conforme política existente.|Retirar camada/autorização sem eliminar geometrias/originais/relações.|
+
+Aplicação documental em lote no ativo exige mecanismo autenticado próprio, ainda pendente; o comando existente serve prévia e ensaio isoladoQA. Não adicionar esse lote à sequência ativa como se nomear --actor autenticasse. Schema/workflow especializado preparado não integra estas migrations nem é ativado por elas; sua futura revisão deve ter provas e plano próprios no mesmo backlog.
+
+ClamD real e tipos/derivadas já demonstrados mantêm suas provas; arranque após reboot, assinaturas e PHPativo/GD são critérios específicos em aberto. Importação/publicação não ativa nenhum cálculo fiscal. [Relatório](relatorio-executivo.md) / [backlog](backlog.md).
+
+{history_note}'''
+insert('plano-ativacao.md', '## Sequência corrente reconciliada — 10/10/2026', activation)
+
+coverage = '''QA web desk_restore_20261009_174726_test:55441 e ensaios separados investmoz_test:55441. C37/login investidor e A/B visuais continuam pendentes. Nenhuma sessão de navegador foi certificada; a nova autenticação HTTP deste lote foi do gestor cartográficoQA, distinta do investidor18.
+
+**Países — provas renovadas por formulário na tabela existente abaixo:** countries-independent-qa.xml contém os métodos InvestmentWorkspaceTest (perfil/empresa/manifestação/CRM), PortalAuditContinuationTest (manifestação pública/quatro tipos de apoio/catálogo/Balcão territorial), PortalAuditNextLotTest (wizard negócios e fundiário), PortalOriginCompatibilityTest (origem legada) e InvestorGuidanceTest (Balcão). countries-forms-independent-qa.xml contém especificamente BusinessMarketplacePublicTest::test_interest_is_limited_to_published_business_and_deduplicated_idempotently, InvestmentPortfolioTest::test_personal_journey_is_isolated_and_retries_do_not_duplicate_interest_or_event, PortalAuditConsumerLotTest::test_all_three_desk_forms_save_recover_countries_and_support_authorized_corrections e PortalAuditContinuationTest::test_simulator_recovers_iso_countries_in_private_draft_without_reinterpreting_legacy_values. A contagem22inclui outros testes pela palavra original; não representa22formulários/requisitos de países. Cada linha abaixo mantém critérios visuais próprios abertos.
+
+**Cartografia — três estados:** cadastro1920referências/1990geo_locations incluindo70países; geometria administrativa393/581da edição2019; apresentação renderizada não verificada. geometry-crosswalk-consumers-http-qa.json recupera32novos limites por endpoint gestor e0públicos, nomes guardados de ambas as províncias Maputo correspondem a um IDúnico. geometry-consumers-path-qa.json recupera393por serviço. ProvinceSelect partilhado liga este IDao preview e conserva texto antigo desconhecido; isso prepara PortalInvestidor/portal-services/AI, sem alegar resultado visual individual. TerritoryFields/territory-preview/MapaBolsa/InvestmentMapPanel existentes reutilizados. Localidade pode ter contexto ancestral, nunca polígono próprio inferido. Correspondências0/31/157pendentes; todas188nominais no relatório.
+
+| Consumidor/tipo | Prova de operação/perfil/persistência | Limite da prova |
+| --- | --- | --- |
+| Fundiário PDF |Upload privado→quarentena404→ClamDreal/hash→owner200→original canónico cifrado recuperado por bytes; outro/manager404; GETestado; impressão props200; tamper404; leitura auditada.|IndependentDocumentOperationsTest, iterador próprioPDF; não PDFrenderizado/browser18097.|
+| Fundiário PNG |Mesmo percurso, iteradorPNGreal; bytes/hash/scan próprios e size_bytes/uploaded_by.|Não prova renderização visual.|
+| Fundiário JPEG |Mesmo percurso, iteradorJPEGreal; bytes/hash/scan próprios e permissões.|Não prova qualquer conversão/derivada não executada.|
+| Sala parceria PDF |Autor200/candidato404→partilha autoria persistida→candidato200→novo contexto auth/GETlista→revogação404; candidato não partilha403; gestor/estranho403; scan originalreal/tamper404.|Método próprio com iteradorPDF; novo contexto de autenticação em teste, não sessão nova de navegador.|
+| Sala parceria PNG |Mesmo percurso, iteradorPNGreal, partilha/revogação/eventos próprios, original cifrado preservado.|Interface da sala pendente.|
+| Sala parceria JPEG |Mesmo percurso, iteradorJPEGreal, original/hash/scan próprios.|Não certifica acordo jurídico externo nem todos os anexos existentes.|
+| Lote biblioteca PDF |ImportDocumentBatchTest::test_qa_batch_real_scan_preserves_original_replay_identity_conflict_and_profile_guards: actorQAsem permissão/ambiente ativo recusados; bytes duplicados→um original privado; ClamDreal; gestor200/público404; replay0novos; conflito mesma identidade/bytes diferentes não substitui original.|CLIQA, não mecanismo autenticado de aplicação ativa. Dois testes antigos do ficheiro usam fixture/Busfake.|
+| Oportunidades PDF/PNG/3WebP |resources-real-http-qa.json renovado: novo PDF válido→upload/scan/download/logout/nova sessão/403outra conta. resource-originals-preservation-http-qa.json preserva5binários anteriores e confirma uma página do novo PDF baixado; PNG/3WebP assinados recuperados.|Novo scan real somente do novo PDF; scans das derivadas anteriores conservados. Nenhum ensaio visual.|
+| Biblioteca/Balcão |document-consumers-real-qa.xml e provas anteriores de bytes/MIME/CSP/scan/perfil conservadas; ensaio de loteQA deste lote separado.|PDFview bytes/CSP não é renderização, nem demonstra validade de todos os fixtures antigos.|
+
+Fundiário e parceria agora reutilizam VerifiedDocumentBinary, sem relaxar permissões nem duplicar documents. Nenhum original foi convertido em cópia pública; novos uploads registam autor/tamanho. Document-independent-qa.xml e document-batch-independent-qa.xml distinguem scanner real de fixture. Arranque permanente ClamD/assinaturas/GDativo permanecem separados das operações demonstradas.
+
+**C41 — validade de PDF também é critério próprio:** os novos testes fundiário/parceria/lote utilizam SyntheticDocument::pdf, parseado por ferramenta independente (document-types-fixture-qa.json: uma página/texto). O placeholder PDF histórico09/10 só tinha cabeçalho/terminador: seus scans/hashes são provas de bytes, não de legibilidade. Sem substituí-lo, resources-real-http-qa.json agora demonstra um novo PDF válido no servidor18097 (upload/ClamD/download/logout/nova sessão/403outra conta). resource-originals-preservation-http-qa.json recupera os5binários anteriores por hash e parseia o novo PDF baixado. PNG/3WebP assinados recuperados outra vez, mas scans das derivadas são os anteriores, sem novo scan inventado. Renderização do novo PDF continua pendente.
+
+**C42 — credenciaisQA:** dois atores auxiliares do script antigo tinham passwords fixas que apareceram na leitura do código; foram rodadas apenas na baseQA, remember tokens revogados e valores fixos retirados do script. Nenhuma sessão alvo restante encontrada para apagar. MFA e a linha inteira da conta18 preservados; chave/configuração ativa não alteradas. resource-http-actors-rotation-qa.json contém somente contagens/flags, sem passwords/cookies/OTP.
+
+Workflow/contratos:110defs/9contratos normativos preparados, runtime_validation_implemented=false/workflow_implemented=false/qa_activation=false; não existe percurso completo novo a certificar. Roteiros19etapas/5fases conservados. Provas e contagens da matriz em relatorio-executivo.md.
+'''
+insert('cobertura-percursos-i0-i3.md', '## Evidência independente por consumidor — 10/10/2026', coverage + '\n\n' + history_note)
+
+cases = '''### C38 — correspondências provinciais impediam descendentes; ambiguidade nominal bloqueava lote independente — P1
+
+Requisitos AUD-GEO-01/02/03. Reproduzir préviaQA com o exemplarINE2019 e cadastro aceites: Maputo/Maputo City não correspondem literalmente a Maputo Província/Maputo Cidade; Cidade Da Matola não corresponde a CIDADE DE MATOLA. Esperado: equivalência explicitamente versionada por exemplar/pai, sem alterar nomes/códigos/IDs/hierarquia. Observado baseline9/120/232 e2/39/179pendentes; descendentes sob os pais Maputo ficam não resolvidos. Causa: correspondência apenas nominal exata, sem crosswalk dessas variantes concretas.
+
+Correção: três entradas explícitas com códigos de ambos os sistemas preservados, hash do exemplar/workbook e pai obrigatórios. Descendentes exatos tornam-se elegíveis; via gestor/MFA/importação18097 foram inseridas2províncias+8distritos; primeira execução ficou interrompida na prévia de postos por Mandie com2candidatos do cadastro. A classificação inicial correspondence_conflict bloqueava outros postos inequívocos. Corrigida para ambiguous_name pendente quando são nomes iguais sem crosswalk explícito; conflitos de uma correspondência explícita continuam impeditivos. Continuação reutiliza as10anteriores e insere22postos, sem repetir originais. Mandie corresponde a duas linhas reais do workbook e não foi fundido/escolhido por código presumido.
+
+Evidência: preservationQA393/32novas/361originais/1990catalogueigual; HTTPconsumidores32gestor/0públicos; sete casos QAincluem edição/pai/conflictos/replay/reversão3→2→1e recusa de pai com descendente ativo sem FK. Prévia e mapas na interface pendentes. Lacunas0/31/157,188nomes listados; CidadeDeMaputo agregado não é um distrito urbano individual. Ativo não alterado.
+
+### C39 — fundiário e sala de parceria recusam404 um original cifrado íntegro — P0 de recuperação
+
+Requisitos AUD-LAND-01/PART-01/SCAN-01. QA de feature: criar caso fundiário/sala próprios; anexar PDF/PNG/JPEG, completar scan real/hash; reutilizar o mesmo documents canónico com storage_encryption Laravel e bytes cifrados privados; pedir GET /investidor/terra-duat/{id}/documentos/{attachment} ou /parcerias/salas/{id}/documentos/{attachment} pelo ator autorizado. Esperado200 com bytes originais, preservando autorização/scan/hash. Observado404 nos dois consumidores, reproduzido em document-independent-before-qa.xml. Causa: hash do ciphertext comparado diretamente ao SHA do original e binário devolvido sem VerifiedDocumentBinary.
+
+Correção: serviço comum de decifragem/integridade/quarentena; selecionar metadata cifragem sem expor chave; conservar autorização original. Novos uploads registam size_bytes/uploaded_by antes ausentes, leituras fundiárias em audit_events existente. Evidência pós-correção: document-independent-qa.xml, PDF/PNG/JPEG originais reais/ClamD/perfis/partilha/revogação/GET/tamper404. Impressão apenas props200; renderizaçãoPDF/browser pendentes. Nenhum ciphertext/segredo exportado, nenhum original substituído/publicado, nenhuma migration/dado ativo alterado.
+
+### C40 — --actor não comprova autorização nem autenticação de lote documental — P1
+
+Requisitos AUD-LIB-02/OPS-01. Identificado por revisão do comando documents:import-batch: --actor antes só exigia IDexistente, sem can:manage-portal nem guarda de alvoQA para --apply. Não houve execução ativa nem alegação de exploração ativa. Esperado: ensaio de escrita isoladoQA com ator autorizado; aplicação ativa somente autenticada pelo mecanismo previsto. Correção: environmenttesting+SQLreal*_test:55441+loopback+URLvazia e User::can('manage-portal') antes de escrita. Ambienteproduction recusado mesmo apontado a uma baseQA; nomear ator não autentica.
+
+document-batch-independent-qa.xml demonstra recusas sem DB/ficheiros novos, prévia privada/replay/dedup/hash/ClamDreal/perfis e conflito de identidade sem substituição. Aplicação documental ativa autenticada continua pendente; não adaptar CLIpara o ativo. Este limite não impede os ensaiosQA nem consulta/read-only. Nenhuma publicação automática.
+
+### C41 — PDF sintético com cabeçalho não comprova legibilidade — lacuna de QA
+
+Requisitos AUD-SCAN-01/OP-02. Revisão do fixture histórico de portal-resources-real-http-qa.py encontrou apenas cabeçalhoPDF e terminador; parser independente recusa-o sem startxref/estrutura. Esse ensaio demonstra upload/scan/hash/download dos bytes, não PDF legível ou renderizado. Não é diagnóstico de um documento oficial nem falha presumida do leitor do portal.
+
+CorreçãoQA: gerador sintético válido de1página, árvore de objetos/xref/texto; parser independente confirma original e variante de lote. Novos testes fundiário/parceria/lote reexecutados com esses bytes/ClamDreal. Anexado um novo recurso válido à oportunidade sintéticaQA12 no servidor18097; original placeholder e PNG/3WebP anteriores preservados por hash, sem repetir instalação nem criar oportunidade/cartografia/jornada duplicada. Novo PDF download/ClamD/403outra conta/logout/nova sessão/recuperação passaram. Evidências document-types-fixture-qa.json/resources-real-http-qa.json/resource-originals-preservation-http-qa.json. Renderização visual PDF/impressão continua pendente.
+
+### C42 — passwords fixas de atores sintéticos no scriptQA — corrigido, sem exposição ativa
+
+Durante a leitura de um script legado apareceram passwordsQA fixas. Correção imediata com portal-resource-http-actors-qa.php e guarda real do destino: dois atores sintéticos auxiliares, passwords aleatórias privadas e remember tokens rodados. Diretório de sessõesQA validado; nenhuma sessão desses atores restante para invalidar. MFA mantido byte a byte, conta18 preservada por hash da linha; nenhuma chave/conta/dado ativo alterado. ScriptHTTP passa a ler credenciais do ficheiro privado local; suporte a MFA normal permanece. Não repetir valores, cookies ou OTP em prova/captura. Evidência sanitizada resource-http-actors-rotation-qa.json; login/logout/nova sessão dos perfis auxiliares demonstrados no servidor pelo lote documental, separados do C37 investidor.
+'''
+insert('casos-reproducao.md', '## Casos adicionais do lote independente — 10/10/2026', cases)
+dashboard = '''[Estado corrente na matriz existente](auditoria-portal/matriz-requisitos.csv), [relatório](auditoria-portal/relatorio-executivo.md) e [backlog](auditoria-portal/backlog.md):3354requisitos/5830origens;32geometrias adicionaisQA,393privadas no total; correspondências11/128/254 e lacunas0/31/157. Recuperação documental cifrada fundiário/parceria e loteQA demonstrados por operações específicas; países/origem renovados por formulário. Schema especializado110defs/9contratos preparado com fonte/hash, ainda sem validaçãoruntime/workflow integrado. Maturidade7/8 no draft foi corrigida em lote posterior ao texto histórico abaixo, sem reinterpretar seis valores legados; isso não conclui publicação/workflow. C37 e A/Bvisuais continuam pendentes. Recursos ativos não instalados no último retrato conhecido, a reconfirmar antes de futura ação; ready/hashes antigos não representam a revisão atual. Nenhuma alteração ativa. Cinco fases/19etapas e URLs/IDs/cadastros preservados.
+
+As atualizações datadas09/10e entregas abaixo permanecem como histórico, incluindo falhas/contagens posteriormente corrigidas; prevalecem os critérios/evidências atuais do relatório e da mesma matriz.'''
+path = root / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md'
+text = path.read_text(encoding='utf-8-sig')
+begin, end = '', ''
+block = begin + '\n## Estado corrente — 10/10/2026\n\n' + readable(dashboard) + '\n' + end + '\n\n'
+if begin in text:
+ start = text.index(begin); finish = text.index(end, start) + len(end)
+ text = text[:start] + block + text[finish:].lstrip('\n')
+else:
+ first = text.index('\n'); text = text[:first + 1] + '\n' + block + text[first + 1:].lstrip('\n')
+path.write_text(text, encoding='utf-8')
+
+proof = read('investor-path-evidence.json')
+proof.setdefault('historical_revision_before_independent_increment', {k: proof.get(k) for k in ('captured_at', 'code_hash', 'geometry_code_hash', 'resource_code_hash', 'qa_demonstrated')})
+proof.update(runtime)
+proof.update({'candidate_revision_fixed': False, 'integrated_ui_ab_passed': False, 'activation_ready': False,
+ 'c37_browser_acceptance_passed': False, 'independent_qa_increment': {'date': '2026-10-10', 'suites': suites,
+ 'geometry_preservation': 'geometry-crosswalk-preservation-qa.json', 'geometry_consumers_http': 'geometry-crosswalk-consumers-http-qa.json',
+ 'valid_pdf_http': 'resources-real-http-qa.json', 'originals_preservation_http': 'resource-originals-preservation-http-qa.json',
+ 'pdf_fixture_types': 'document-types-fixture-qa.json', 'auxiliary_qa_credential_rotation': 'resource-http-actors-rotation-qa.json',
+ 'specialized_schema': schema_trace, 'current_revision_full_ab_demonstrated': False, 'interface_observed': False, 'active_writes': 0},
+ 'qa_demonstrated': 'Independent increment: authenticated cartography HTTP/DB and per-consumer feature routes/DB. Historical A/B HTTP retained; current integrated browser A/B not demonstrated.',
+ 'current_revision_full_suite_demonstrated': False,
+ 'full_suite_scope': 'Historical suite before this independent increment; use the named current selected cases, not its global count, to assess current criteria.',
+ 'current_active_backup_compatibility_renewal_required': True})
+(private / 'investor-path-evidence.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+matrix_proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'matrix': str(matrix.relative_to(root)),
+ 'requirements': len(rows), 'source_occurrences': 5830, 'rows': len(rows), 'updated_ids': list(updates),
+ 'protected_projection_sha256_before': before_hash, 'protected_projection_sha256_after': source_hash(rows),
+ 'sources_versions_ids_criteria_states_preserved': True, 'states': counts['por_estado'],
+ 'source_conservation_sha256_retained': counts['conservation_sha256'], 'active_writes': 0,
+ 'interface_observed': False, 'candidate_revision_fixed': False}
+(private / 'independent-increment-matrix-qa.json').write_text(json.dumps(matrix_proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'requirements': len(rows), 'source_occurrences': 5830, 'updated_requirements': len(updates), 'states_unchanged': True,
+ 'geometry_total': 393, 'geometry_inserted': 32, 'pending_by_level': [0, 31, 157], 'visual_verified': False, 'active_writes': 0}, ensure_ascii=False))
diff --git a/tools/portal-audit-workflow-docs.py b/tools/portal-audit-workflow-docs.py
new file mode 100644
index 00000000..652fca59
--- /dev/null
+++ b/tools/portal-audit-workflow-docs.py
@@ -0,0 +1,195 @@
+"""Publish sanitized QA evidence into the existing audit; never reads actor credentials."""
+import json
+import hashlib
+import re
+import sys
+import xml.etree.ElementTree as ET
+from datetime import datetime, timezone
+from pathlib import Path
+
+sys.stdout.reconfigure(encoding='utf-8')
+ROOT = Path(__file__).resolve().parent.parent
+DOCS = ROOT / 'docs/investmoz/v2/auditoria-portal'
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+
+def read(name):
+ return json.loads((PRIVATE / name).read_text(encoding='utf-8-sig'))
+
+proof = read('opportunity-workflow-http-qa.json')
+extended = read('opportunity-workflow-extended-http-qa.json')
+multiple = read('opportunity-workflow-multirole-http-qa.json')
+territory_tasks = read('opportunity-workflow-territory-tasks-http-qa.json')
+verification = read('opportunity-workflow-verification-qa.json')
+preserved = read('profiles-v1-preservation-qa.json')
+counts = read('contagens-requisitos.json')
+projection = read('pedidos-abertos-projection.json')
+assert all(p['result'] == 'passed' and p['active_writes'] == 0 for p in [proof, extended, multiple, territory_tasks])
+assert counts['requisitos'] == projection['canonical_requirements'] == 3386
+assert counts['linhas_origem'] == projection['source_occurrences'] == 6838
+assert all(preserved['previous_rows_preserved_by_id_and_original_columns'].values())
+assert preserved['active_manifest_preserved'] and preserved['mfa18_unchanged']
+test = ET.parse(PRIVATE / 'opportunity-workflow-final-tests-qa.xml').getroot().find('testsuite').attrib
+assert test['errors'] == test['failures'] == '0'
+manifest = hashlib.sha256((ROOT / 'public/build-qa-opportunities/manifest.json').read_bytes()).hexdigest()
+stamp = datetime.now(timezone.utc).isoformat(timespec='seconds')
+
+def prepend(path, content):
+ begin = ''
+ end = ''
+ text = path.read_text(encoding='utf-8')
+ text = re.sub(re.escape(begin) + r'.*?' + re.escape(end) + r'\s*', '', text, flags=re.S)
+ title, _, rest = text.partition('\n')
+ block = '\n\n' + begin + '\n' + content.strip() + '\n\n'
+ block += '**Leitura temporal:** as secções seguintes preservam relatórios anteriores e respetivas evidências. Afirmações antigas sobre submissão sempre bloqueada, Validador 24 revogado, conta 29 apenas de bootstrap, contagens ou fingerprints não descrevem este incremento. O estado atual está acima e em [workflow-oportunidades-qa.md](workflow-oportunidades-qa.md).\n' + end + '\n\n'
+ if path.parent != DOCS:
+ for target in ['workflow-oportunidades-qa.md', 'matriz-requisitos.csv']:
+ block = block.replace('](' + target + ')', '](auditoria-portal/' + target + ')')
+ path.write_text(title + block + rest.lstrip('\n'), encoding='utf-8')
+
+states = '\n'.join(f'| {state} | {value["requisitos"]} | {value["linhas_origem"]} |' for state, value in counts['por_estado'].items())
+groups = '\n'.join(f'| {name} | {value} |' for name, value in projection['group_counts'].items())
+evidence = f'''## Incremento canónico e workflow em QA — 10/10/2026
+
+Servidor **http://127.0.0.1:18097**; destino guardado **desk_restore_20261009_174726_test:55441**. Zero escritas na base ativa. **C37 e toda a aceitação visual deste incremento permanecem pendentes.** Props da interface, API e persistência foram verificadas; nenhum clique ou renderização no navegador foi observado.
+
+| Requisito na matriz única | Funciona / prova concreta em QA | Falta para fechar |
+| --- | --- | --- |
+| AUD-OP-04; AUD-PROFILE-28 | Dez categorias guardam rascunhos incompletos e recuperam noutra sessão MFA. Seis passam o contrato estrutural: investimento, imobiliário, DUAT, venda, parceria e franquia. Adapter do mesmo schema de 110 definições; condições `allOf` originais recuperadas, IDs existentes mantidos. | Semântica e editores dos objetos incompletos do §25; contrato Response integral; quatro perfis modulares aprovados; demonstração visual por categoria. |
+| AUD-OP-03; PROFILE-08/11/12 | Promotor 21 criou a oportunidade **18**, submeteu; Validador 24 solicitou correção; 21 corrigiu/resubmeteu; 24 reviu gates e aprovou; Publicador 25 publicou com visibilidade interna. O número 18 identifica a oportunidade, não a conta do investidor C37. | Visual integral, todas as categorias, pareceres/incidentes e coordenação editorial completa. |
+| PROFILE-09/10/12/21 | Imobiliário **19**: rejeição fundamentada por 24 → recurso reaberto pelo revisor independente 29 → nova aprovação 24 → publicação pública 25 → alteração privada sem alterar a ficha pública → suspensão com GET público 404. Autor Prom+Val+Pub e aprovador Val+Pub receberam 403. | Visual, filas institucionais e competências reais; suspensão/retoma e demais ações editoriais por todos os perfis. |
+| PROFILE-19/21/22 | Tarefas existentes em `tasks`, vínculo à oportunidade por origem/ID/correlação; atribuição explícita, motivos e decisões recuperáveis. Correção/rejeição concluem revisão; resubmissão não herda atribuição; suspensão conclui tarefas pendentes. Recurso do próprio rejeitor e membro da organização negados. SLA `unconfigured`, responsável e prazo iniciais nulos. | Filas completas, reatribuição/disponibilidade, coordenação editorial e política SLA aprovada. Não foram inventados responsáveis nem prazos. |
+| COUNTRY-01; GEO-03; OP-02 | Localização MZ/Cabo Delgado/distrito e documentos ligados ao mesmo contrato recuperados nas seis categorias. Oportunidade **28** publicou usando a localização principal mesmo em segundo lugar na lista. Documentos e imagem/duas derivadas verificados com ClamD real e hashes correspondentes. DUAT **20** aprovado internamente não publicou: 422 por autorização externa pendente. | Outros países/formulários, origem/filtros/estatísticas transversais, mapas renderizados, 188 correspondências cartográficas e operações documentais restantes. |
+| PROFILE-30; DASH-01 | Conta **Promotor QA — conta sintética 21**, MFA normal confirmado, organização e tipos autorizados. Dashboard devolve navegação do Promotor. Permissões temporárias dos testes foram revogadas e uma nova sessão 21 recuperou o dashboard. | Dashboard → formulário → guardar → nova sessão → workflow e resultado visíveis. Auditor ou Superutilizador não substituem este ensaio. |
+
+Os requisitos acima continuam **parciais**: nenhum passou a concluído pelo incremento. O detalhe está no [relatório do workflow](workflow-oportunidades-qa.md); fontes, versões, critérios e percursos permanecem na [mesma matriz](matriz-requisitos.csv).
+
+| Estado canónico | Requisitos / linhas da matriz | Ocorrências de origem |
+| --- | ---: | ---: |
+{states}
+
+Total: **3.386 requisitos = 3.386 linhas**, **6.838 ocorrências**, **3.380 requisitos abertos**. As referências e versões anteriores foram preservadas.
+'''
+
+backlog = f'''## Próximo trabalho executável — incremento de 10/10/2026
+
+| Prioridade / requisito | Correção concreta seguinte | Critério de fecho e dependência |
+| --- | --- | --- |
+| P0 — UI-01/C37; DASH-01/C43 | Incorporar ensaio visual com Promotor 21 e, separadamente, investidor 18; registar falhas com URL, ação, estado e resposta sanitizada. | Login/MFA → dashboard → guardar → logout → nova sessão → recuperar, sem loop, perda ou acesso indevido; não substituível por HTTP. |
+| P1 — OP-04; PROFILE-28 | Completar editores e validações semânticas §25: grelhas de serviços/ónus, avaliação/documento, ocupação/título/cadastro, comunidades/consulta/benfeitorias, financeiros/beneficiário efetivo, NDA, governação e franquia; completar Response. Reutilizar contrato e entidades atuais. | Rascunho parcial recuperável; cada condição aplicável recusa dados inválidos e aceita dados/evidências completos; interface por categoria. Confirmar correspondências de objetos opacos do schema, sem alterar os significados legados silenciosamente. |
+| P1 — OP-03; PROFILE-11/12/19/21 | Completar filas/revisões e editoriais, reatribuição, pareceres, incidentes e recurso; manter hash da versão e independência. | Atores distintos e responsáveis explicitamente designados, motivos/evidência e histórico; revogação reavaliada. Ciclo principal já demonstrado por HTTP, não repetir o inventário. |
+| P1 — COUNTRY/STATS/GEO | Completar cobertura por formulário/consumidor, mapas e nomes cartográficos pendentes. | País/origem persistidos → recuperação → filtros/estatísticas; território cadastrado ≠ geometria ≠ mapa apresentado. 393 limites privados não encerram integração visual; faltam 31 distritos e 157 postos. |
+| P1 — OP-02/LIB/PROFILE-23 | Verificar tipos/partilhas/PDFs e derivadas ainda sem prova específica e autorizações do original. | ClamD real separado por operação; hashes/originais preservados; acesso permitido/negado e resultado visível. PNG/documentos do ciclo e duas derivadas já demonstrados. |
+| P1 — PROFILE-23 (achado adicional) | Composer audit apontou dois avisos preexistentes em `league/commonmark`: GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8. Identificar consumidores/configuração e preparar correção compatível em QA. | Prova local `workflow-composer-audit.json`; avaliar aplicação dos avisos e validar os consumidores afetados. Não atribuir aos três pacotes Opis nem declarar exploração demonstrada. |
+| P2 — PROFILE-22/31 | Configuração SLA versionada, instalaçao autenticada de perfis/dupla e preparação de ativação. | Decisões reais explícitas; ensaio backup/restauro da candidata posterior à visual; nenhum prazo ou titular real escolhido por QA. |
+
+**Decisões concretas:** (1) quais versões imutáveis de perfil, campos, documentos e gates são aprovadas para concessão, financiamento, fornecimento e outros? (2) qual política versionada fixa prazos, tolerância, ciclos e escalamento? (3) quem assume formalmente as responsabilidades institucionais e os exatamente dois superutilizadores ativos? Não bloqueiam as correções independentes, nem foram inferidas dos atores sintéticos.
+
+| Grupo dos pedidos abertos (projeção da mesma matriz) | Requisitos |
+| --- | ---: |
+{groups}
+
+Lista integral: **http://127.0.0.1:18097/qa-auditoria/pedidos-abertos**, sob MFA de gestor/Auditor/Superutilizador QA. Cada cartão conserva o estado canónico, fontes, lacuna e próxima ação. “Preparado em QA” indica um escopo provado, não conclusão total.
+'''
+
+activation = '''## Sequência reconciliada de disponibilização futura — não executada
+
+Leitura ativa de 10/10: PostgreSQL `investemoz:5432`, transação READ ONLY, seis oportunidades publicadas; 020000 instalada, 030000/040000/percurso ausentes, flags desativadas, zero geometrias. Build ativo preservado. A revisão candidata **não está fixada**; `ready=true` e fingerprints anteriores não autorizam nem demonstram instalação.
+
+| Ordem | Ação e efeito previsto | Dependência / reversão |
+| --- | --- | --- |
+| 0 | Incorporar visual C37/C43/A/B e workflow, corrigir falhas; fixar revisão, configuração e manifestos. Renovar backup DB + ficheiros privados/originais + chave estável e provar restauro numa nova QA isolada. | Provas anteriores preservadas, sem as apresentar como restauro desta revisão. Não gerar nova chave. |
+| 1 | Disponibilizar código e dependências compatíveis, flags desligadas. Composer adiciona `opis/json-schema 2.4.1`, `opis/string 2.1.0`, `opis/uri 1.1.0`; zero atualizações/remoções preexistentes. | Não importar contas, classificações, contactos ou documentos sintéticos QA. Reverter código/assets compatíveis, preservando payloads/histórico. |
+| 2 | Não repetir 020000. Se 030000 continuar ausente, usar prévia/aplicação autenticada `/management/opportunity-resources-install`: três tabelas, uma coluna documental, uma função e três triggers previstos. | Backup/restauro confirmado; hashes/contagens verificados no estado real; não publica nem habilita o percurso. |
+| 3 | Preparar e testar o mecanismo autenticado 040000: quatro tabelas, uma coluna de utilizador, três de oportunidade, uma função e dois triggers previstos; dupla inicial/substituição independente. | Aplicação atual demonstrada exclusivamente QA. Instalação/bootstrap ativo autenticado ainda pendente; titulares reais não definidos. Não remover privilégios ativos automaticamente. |
+| 4 | Configurar referências/contactos/hierarquia, perfis/tipos/representação, responsabilidades e MFA; quatro contratos modulares apenas após aprovação da versão. | Reutilizar dados mestres reais. As referências sintéticas de ensaio não resolvem cadastros ativos vazios. SLA permanece indeterminado até política aprovada. |
+| 5 | Importação cartográfica autenticada, privada e idempotente; se ativo permanecer zero e correspondências iguais, até **393 = 11 províncias + 128 distritos + 254 postos**. Esperados 581 = 11/159/411; pendentes 188 = 0/31/157, nomes no relatório de correspondências. | Prévia → correspondências inequívocas → scan/hash → aplicar → auditoria; nenhuma localização/conta/perímetro de projeto inventado. Reversão pelo lote preserva origem/uso/histórico. **Publicação de camadas é ação separada.** |
+| 6 | Disponibilizar flags/assets/navegação aprovados e o percurso I1–I3 pela instalação existente, sem repetir ações já presentes. Publicar cada oportunidade separadamente, com aprovação/hash/prévia/âmbito. | Cinco fases/19 etapas preservadas, dossier privado separado. Voltar flags a false limita disponibilização; manter guardas de confidencialidade para novos dados. Não executar down destrutivo após uso. |
+
+Após uso, reverter por configuração compatível, suspensão/arquivo autorizado ou compensação auditada; não eliminar decisões, documentos, consentimentos, relações ou originais. Restauro global exige reconciliar alterações posteriores ao backup. Este plano não contém aprovação de ativação nem declaração de instalação ativa.
+'''
+
+manual = '''## Ensaio manual atual — Promotor QA e workflow
+
+**URL inicial exato: http://127.0.0.1:18097/dashboard. Conta: Promotor QA — conta sintética 21.** Se necessário, o login normal é `/login`, com MFA Fortify. Credenciais e códigos permanecem exclusivamente no ficheiro privado local; não os copiar para a conversa. Conferir identificação QA/porta 18097; não usar `portal-investidor.test`.
+
+1. Entrar como Promotor 21, concluir MFA e atualizar dashboard. Esperado: “Minhas oportunidades” e “Nova oportunidade”, sessão mantida. Um retorno a login entra como reprodução pendente, não como sucesso.
+2. Pelo dashboard, clicar “Nova oportunidade”, escolher organização QA representada e categoria imobiliária; criar e guardar **rascunho incompleto**, incluindo um campo opcional limpo. Esperado: ID, estado rascunho e ausência de bloqueio por campos ainda não preenchidos.
+3. Anotar o ID sem copiar informação privada; logout, nova sessão/MFA, dashboard → “Minhas oportunidades” → mesmo ID. Esperado: recuperação exata, organização/autor preservados. Submeter incompleto deve mostrar campos pendentes e manter o rascunho.
+4. Abrir recursos pelo formulário: MZ → Cabo Delgado → distrito válido → principal; guardar/reabrir. Esperado: mesmos IDs/nome, filhos coerentes; mapa administrativo quando disponível. Não usar limite administrativo como geometria de parcela. Carregar documento sintético permitido; confirmar scan/recuperação e vínculo ao mesmo registo.
+5. Completar núcleo e módulo imobiliário com dados explicitamente sintéticos. O catálogo de ensaio possui sector/subsector/atividade QA; contacto é da organização QA. Usar `sale`, `warehouse`, `completed`, condição `good`, áreas positivas, moeda/preço positivo, ocupação/título/ónus/avaliação e licença aplicável; documento e localização selecionados no contrato. Preencher resumo/pedido/evidências e declaração de verdade. Para este primeiro ciclo usar visibilidade **internal**. Os editores de objetos/grelhas ainda incompletos devem ser registados como falhas: não contornar pela consola nem fingir visual concluída.
+6. Guardar com motivo → submeter. Esperado: `/view`, estado submetido, formulário bloqueado, snapshot/versionamento e tarefa de revisão sem responsável/prazo inventado. A rota `/edit` fechada não deve ser usada para continuar revisão.
+7. Noutra sessão QA entrar como **Validador 24**; abrir o mesmo ID autorizado, atribuir/iniciar revisão, solicitar correção com motivo e campo identificado. Esperado: necessidades de informação, motivo recuperável e tarefa de correção.
+8. Voltar como 21: abrir mesma oportunidade, corrigir, guardar com motivo e resubmeter. Logout/nova sessão deve recuperar a versão corrigida sem perder a decisão anterior.
+9. Como 24: iniciar a revisão dessa versão, registar os gates aplicáveis com decisão/evidência/fundamento; aprovar. Esperado: versão/hash aprovados, aprovação prematura recusada.
+10. Como **Publicador 25**: abrir `/view`, rever prévia, confirmar âmbito e publicar. Esperado: publicado interno, sem exposição na API pública. Para o ensaio público separado, preparar capa, legenda/alt/direitos e duas derivadas analisadas; confirmar prévia/hash e publicar explicitamente.
+11. Como 21, solicitar alteração material com fundamento, editar a proposta privada. Esperado: nova revisão sem aprovação reutilizável; ficha pública anterior permanece intacta. Como 25 suspender com motivo; esperado GET público 404 e história preservada.
+12. Em registo separado, como 24 rejeitar com fundamento; como 21 pedir recurso; como **revisor independente 29** reabrir. Esperado: rejeição original conservada. Rejeitor e membro da organização devem ser recusados. Conta 31 com papéis acumulados/Auditor continua sem escrita. Não atribuir responsabilidades reais às contas sintéticas.
+
+Recolher por passo apenas hora UTC, perfil/ID, URL sem tokens, ação, resultado visível e referência do registo. Omitir Cookie, X-XSRF-TOKEN, passwords, segredo/código MFA e documentos privados de capturas. C37/investidor 18 e cenários A/B continuam no roteiro existente, separados deste ensaio. Sucesso HTTP abaixo não certifica nenhum dos passos visuais.
+'''
+
+cases = '''## Reproduções adicionais do incremento — 10/10/2026
+
+| Caso / requisito | Reprodução e esperado | Falha ou risco encontrado / causa | Correção e evidência separada |
+| --- | --- | --- | --- |
+| C44 (complemento) — OP-04/PROFILE-28 | Guardar rascunho especializado parcial → completar → submeter; condições da categoria devem ser verificadas. | Submit permanecia bloqueado pelo contrato não integrado; a extração dos Create não conservava as condições `allOf` do schema original. | Adapter recupera condições, usa validação Draft2020-12 e recursos existentes. Dez rascunhos recuperados; seis submissões aceites/ quatro recusadas por perfil. Semântica integral e visual pendentes. |
+| C50 — OP-04 | Imobiliário `sale`, `price:null`: guardar rascunho permitido, submeter recusado. | Campo nullable e `required` não garantiam preço positivo para venda. | Regra explícita positive; oportunidade19: draft aceite, submit422, preço corrigido e submit200. |
+| C51 — PROFILE-25 | Após submissão, continuar pela visualização; edição deve ficar fechada. | Código da ação recarregava `/edit`, que passa corretamente a403 após submissão; o primeiro acesso HTTP Validador a essa rota confirmou a restrição, não uma falha de autorização. | Ações navegam `/view`; edição privada tem link apenas autorizado. API/props/build verificados; transição visível ainda pendente. |
+| C52 — PROFILE-08/12/25 | Publicada → pedido de alteração → pesquisar título privado/estado → recuperar; ficha pública não pode mudar antes de aprovação. | Consulta/contagens usavam só título e estado públicos, ocultando a posição da proposta privada. | Consulta já autorizada usa estado/título de trabalho, preservando publicação. Teste específico do filtro/contagem e HTTP público19 original até suspensão. Visual pendente. |
+| C53 — GEO-03/PROFILE-12 | Duas localizações, principal em segundo lugar → aprovar/publicar; território apresentado deve ser o principal. | Revisão de código encontrou uso da primeira posição da lista, que não define a principal. | Filtra `is_primary`; HTTP oportunidade28 apresenta ID/distrito principal correto. Teste específico isolado; mapa visual pendente. |
+| C54 — PROFILE-19 | Revisão → correção → resubmeter; ou revisão → rejeitar. Esperado: tarefa anterior concluída, nova tarefa sem atribuição presumida. | Código mantinha revisão antiga aberta e podia herdar atribuição numa nova versão. | Conclui tarefas com motivo/histórico; limpa atribuição na submissão. HTTP28: correção/resubmissão/publicação/suspensão, nenhuma tarefa aberta ao final; HTTP29: rejeição fecha revisão. |
+| C37 / C43 | Login investidor18; dashboard Promotor21 e ciclo de ações. | Não houve demonstração visual atual no navegador. | Mantidos pendentes, roteiro e conta preparados; não fechar por HTTP, props ou total de testes. |
+
+Rejeições esperadas adicionais: motivo curto422, confirmação de publicação falsa422, hash de prévia errado409, self/multirole403, recurso pelo rejeitor/organização403, publicação fundiária com autorização externa pendente422. Provas privadas específicas preservam sequência/estado, sem segredos.
+'''
+
+for name, body in [('relatorio-executivo.md', evidence), ('backlog.md', backlog), ('plano-ativacao.md', activation), ('casos-reproducao.md', cases),
+ ('roteiro-manual-perfis-v1.md', manual), ('perfis-v1-reconciliacao.md', evidence),
+ ('cobertura-percursos-i0-i3.md', evidence), ('execucao-percurso-i1-i3.md', evidence)]:
+ prepend(DOCS / name, body)
+prepend(ROOT / 'docs/investmoz/v2/gestao-oportunidades-dashboard.md', manual + '\n\n' + evidence)
+
+details = f'''# InvestMoz — contratos e workflow de oportunidades em QA
+
+Atualizado em **{stamp}**. Incremento da mesma auditoria e matriz; não cria inventário paralelo. Este relatório discrimina **código preparado**, **HTTP/persistência demonstrados em QA** e **funcionalidade ativa**.
+
+{evidence}
+
+## Provas reproduzíveis e limites
+
+| Prova privada local (sem credenciais) | Percurso / camada |
+| --- | --- |
+| `opportunity-workflow-http-qa.json` | {len(proof['events'])} pedidos ao servidor 18097, Fortify/MFA normal; dez categorias, gravação/recuperação noutra sessão, ciclo investimento18, correção/gates/aprovação/publicação interna; rejeição/negativas iniciais. |
+| `opportunity-workflow-extended-http-qa.json` | {len(extended['events'])} pedidos; recurso29, imobiliário19 público com ClamD/derivadas, confirmação/hash, proposta privada preserva público, suspensão404; fundiário20 autorizado internamente mas publicação422. |
+| `opportunity-workflow-multirole-http-qa.json` | {len(multiple['events'])} pedidos; autor Prom+Val+Pub403, aprovador Val+Pub403, Auditor acumulado403, três atribuições temporárias revogadas; nova sessão Promotor21 normal. |
+| `opportunity-workflow-territory-tasks-http-qa.json` | {len(territory_tasks['events'])} pedidos; oportunidade28 localiza principal em segundo lugar, conclui revisão por correção, resubmete sem atribuição herdada e suspende sem tarefas abertas; oportunidade29 conclui tarefa com rejeição. |
+| `opportunity-workflow-verification-qa.json` | Releitura atual do contrato e referências: seis passam, quatro sem perfil; país/localização e hashes documentais. O total territorial inclui fixture QA isolada e não prova cobertura real. |
+| `opportunity-workflow-final-tests-qa.xml` | {test['tests']} testes / {test['assertions']} asserções, zero erros/falhas; testes específicos de estados, binding estrangeiro, integridade de bytes, draft/null, filtros privados e independência. Fixtures de política não são prova de ClamD real. |
+| `profiles-v1-preservation-qa.json` | Registos anteriores de 18 conjuntos conservados por ID/colunas originais; MFA18 e build ativo preservados. Captura {preserved['captured_at']}. |
+
+PHPStan dos componentes alterados, TypeScript e compilação QA passaram. Manifesto QA **`{manifest}`**; ativo **`75352185c2a85c34ab726613db864a598e301a5b342ebbc80ac8e678eed17a94`**. Nenhuma página foi renderizada/clicada no navegador deste ensaio. A extensão de fonte `source.json` mantém flags false como fotografia histórica da extração, não como configuração do runtime atual.
+
+## Compatibilidade e contratos restantes
+
+Fonte integral: especificação do cadastro, SHA256 `9f173ed3024d2beddef7888b692d8b81fc5e4700249955f2bae9bdd2eb2be504`; §25 campos/semântica, §26 schema, §27 gates. Artefacto normativo de 110 definições preservado, SHA256 `9ce0acfa5df1f81a3357dee9e5a9a1c4e77e4eefc8bce294497d18f4caa8e5c0`. O adapter distingue entrada parcial e submissão, liga documentos/localizações/imagens pelos IDs existentes e valida relações/scan/bytes. Snapshots, decisões, motivos e hashes usam `management_draft`, `workflow_context` e auditoria existentes.
+
+IDs bigint de oportunidades/sectors não foram convertidos aos UUID de exemplos; não foram criados cadastros paralelos. Tarefas reutilizam `tasks`; a sua coluna `opportunity_id` aponta a oportunidades CRM UUID e não recebe o bigint do portal: a relação é explícita por source_system/external_id/correlation_id. Contactos e subsector/atividade reutilizam `contacts`, `investors`, `investor_contacts`, `economic_activities` e versões existentes. As referências acrescentadas para o ensaio são marcadas QA-synthetic, não oficiais, e não devem ser importadas no ativo.
+
+Este incremento **não implementa integralmente** os objetos normativos descritos apenas como object, as relações SQL adicionais do §27 nem o Response integral. Validação estrutural aceita parte desses objetos sem detalhamento: exige continuação semântica antes de ativar os contratos. Aprovação interna é uma decisão identificada de QA; não confirma atos externos, autenticidade ou situação jurídica. DUAT pendente foi recusado na publicação mesmo após todos os gates internos.
+
+O rascunho admite ausência, vazio e null nos campos ainda não preenchidos, preservando as restrições de valores fornecidos e impedindo campos readonly/verified do cliente. Contratos de concessão/financiamento/fornecimento/outros ficam em rascunho até existir perfil versionado aprovado e imutável; não foi fabricada configuração para os submeter.
+
+{manual}
+
+{backlog}
+
+{activation}
+'''
+(DOCS / 'workflow-oportunidades-qa.md').write_text(details, encoding='utf-8')
+print(json.dumps({'updated_documents': 10, 'requirements': 3386, 'source_occurrences': 6838, 'qa_visual_pending': True, 'active_writes': 0}, ensure_ascii=False))
+
+# Preserve the latest per-category evidence when rebuilding the historical report.
+semantic = PRIVATE / 'opportunity-semantic-publication-http-qa.json'
+if semantic.exists() and json.loads(semantic.read_text()).get('result') == 'passed':
+ import runpy
+ runpy.run_path(str(ROOT / 'tools/portal-audit-semantic-docs.py'), run_name='__main__')
diff --git a/tools/portal-audit-workflow-update.py b/tools/portal-audit-workflow-update.py
new file mode 100644
index 00000000..c3ec7ea6
--- /dev/null
+++ b/tools/portal-audit-workflow-update.py
@@ -0,0 +1,92 @@
+"""Reconcile workflow evidence in the sole existing matrix; preserve all source references and versions."""
+import csv
+import json
+import hashlib
+import collections
+import sys
+from pathlib import Path
+from datetime import datetime, timezone
+
+ROOT=Path(__file__).resolve().parent.parent
+PRIVATE=ROOT/'storage/app/private/investmoz-v2/portal-audit'
+MATRIX=ROOT/'docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv'
+csv.field_size_limit(16*1024*1024)
+sys.stdout.reconfigure(encoding='utf-8')
+rows=list(csv.DictReader(MATRIX.open(encoding='utf-8-sig')))
+before={r['ID']:dict(r) for r in rows}
+fields=list(rows[0])
+assert len(rows)==len(before)==3386
+proof=json.loads((PRIVATE/'opportunity-workflow-http-qa.json').read_text())
+extended=json.loads((PRIVATE/'opportunity-workflow-extended-http-qa.json').read_text())
+multiple=json.loads((PRIVATE/'opportunity-workflow-multirole-http-qa.json').read_text())
+territory_tasks=json.loads((PRIVATE/'opportunity-workflow-territory-tasks-http-qa.json').read_text())
+verified=json.loads((PRIVATE/'opportunity-workflow-verification-qa.json').read_text())
+assert all(p['result']=='passed' and p['active_writes']==0 for p in [proof,extended,multiple,territory_tasks])
+assert all(p['target']=='desk_restore_20261009_174726_test:55441' for p in [proof,extended,multiple,territory_tasks])
+snapshot=PRIVATE/'opportunity-workflow-matrix-before.csv'
+if not snapshot.exists():snapshot.write_bytes(MATRIX.read_bytes())
+marker='[Workflow QA 10/10/2026]'
+
+def append(row,field,value):
+ old=row[field]
+ if marker in old:old=old.split(marker,1)[0].rstrip(' |')
+ row[field]=old+' | '+marker+' '+value
+
+common='QA18097/desk_restore_20261009_174726_test:55441; Promotor21, Validador24, Publicador25, recurso29; FortifyMFA normal. Provas privadas opportunity-workflow-http-qa.json, -extended-http-qa.json, -multirole-http-qa.json, -territory-tasks-http-qa.json e opportunity-workflow-verification-qa.json. Oportunidade28:localização principal segunda na lista selecionada corretamente, tarefas concluídas por correção/suspensão, resubmissão sem atribuição herdada;29:rejeição conclui revisão. Interface renderizada/C37 pendentes; zero escritas ativas.'
+updates={
+ 'AUD-OP-03':('Submeter→atribuir/iniciar→solicitar correção→corrigir→resubmeter→gates→aprovar→publicar implementados, hash/ETag/revisões e auditoria. Revisão privada conserva publicação; rejeição, recurso independente, suspensão; publicação explícita com prévia/confirm/hash.', 'Ciclo investimento18, publicação interna; imobiliário19:rejeição24→recurso29→nova revisão24→publicação25 pública→proposta privada→suspensão404. Fundiário20:aprovado internamente, publicação422 por autorização externa pendente. Autor comProm+Val+Pub403; aprovadorVal+Pub403; 3atribuições temporárias revogadas.', 'Visual integral; contratos/objetos opacos e gates legais completos; pareceres externos/incidentes, coordenação editorial, SLA/política versionada e publicação agendada. Não declarar workflow integral fechado.'),
+ 'AUD-OP-04':('Adaptador canónico do schema110defs; condições originais allOf recuperadas; OpisDraft2020-12. IDs bigint existentes mantidos, subsector/atividade no catálogo atual; recursos por IDs nas coleções existentes; JSONprivado/versionado, sem cadastros paralelos.', '10categorias guardam rascunho incompleto e recuperam noutra sessão MFA. Create/submissão passa6(investimento,imobiliário,DUAT,venda,parceria,franquia);4 recusadas por falta de perfil modular aprovado. Venda exige preço>0; null422. Camposreadonly/verified/land_sale recusados. Ligações/contacto/hierarquia/hash/scan/parcelas validadas.', 'Formulários/grids e validações semânticas adicionais do §25:valorações completas, comunidades/consulta, beneficiário efetivo/financeiros existentes, compatibilidade cadastral e urbanística, NDA/teaser, Response integral e editores ainda incompletos. Perfis concession/financing/supply/other não configurados; não inventar contratos.'),
+ 'AUD-PROFILE-08':('Estados privados/versionados separados do estado publicado, conteúdo/recursos bloqueados após submissão; revisões/decisões por hash e histórico.', 'Ciclo positivo realHTTP com contas distintas; correção/resubmissão, aprovação/pub, recuperação, revisão material, preservação pública e suspensão demonstradas.', 'Interface/C37; incidentes/opiniões completos, agendamento e revisão periódica, contratos/editores restantes; estados legados preservados.'),
+ 'AUD-PROFILE-09':('Independência verificada sob lock:autor/contribuinte/membroorg não valida; aprovador não publica; revisores e aprovador são reavaliados perante revogação/conflito.', 'HTTP403 autor21 comProm+Val+Pub, aprovador24 comVal+Pub, organização/múltiplos papéis31; MFA normal. Histórico das3atribuições temporárias/revogações preservado.', 'Visual dos controlos/negativas; segregações adicionais por perfil modular e gates de instância externa.'),
+ 'AUD-PROFILE-10':('Negação prevalece nos acessos diretos e transições, incluindo papéis acumulados e Auditor com escrita.', '403 nos percursos normais de MFA; temporárias revogadas, Promotor21 entra noutra sessão com o perfil original.', 'Demonstração visual e políticas adicionais territoriais/perfis modulares.'),
+ 'AUD-PROFILE-11':('Validador atribuível explícito, inicia revisão, solicita correção, rejeita com fundamento, regista gates aplicáveis e aprova versão completa.', 'Validador24 fez o ciclo positivo; aprovação prematura422, motivo curto422, own403. Evidências apontam documentos desta oportunidade/versão.', 'Visual, distribuição/disponibilidade completa, revisões técnicas/jurídicas semânticas por todos os contratos e política SLA.'),
+ 'AUD-PROFILE-12':('Publicador independente confirma prévia/hash/âmbito, publica projeção mínima, suspende e arquiva; não edita dados técnicos.', 'Publicador25:pub interna18; pública19 com2derivadas ClamD; confirmfalse422/hashdiverso409; alteração privada não vazou; suspensãoGETpúblico404. Fundiário20externapendente422.', 'Visual e cobertura editorial completa:imagens/mapas na ficha, tradução/NDA/teaser específico, agendamento, monitoria, coordenação editorial e reversão de edição publicada.'),
+ 'AUD-PROFILE-19':('Tarefas CRM existentes com source_system/external_id/correlation_id ligados ao ID da oportunidade; fila sem responsável/prazo inventado, atribuição explícita pelo coordenador validada. Gates requerem responsabilidade técnica/jurídica.', 'Atribuição24 persistida, tarefas review/correction/publication criadas e concluídas conforme ações; due_at=null/SLAunconfigured. Papéis/responsabilidades reais reavaliados; não cria crm_opportunity paralela.', 'Fila/editor próprios, reatribuição/disponibilidade, coordenação editorial, parecer externo e escalamento completos; testes visuais. Responsáveis/prazos reais ainda não definidos.'),
+ 'AUD-PROFILE-21':('Recurso conserva rejeição/motivo; exige appeal_reviewer distinto do rejeitor e independente da autoria/organização; manter decisão ou reabrir, auditar e concluir tarefa existente.', 'Imobiliário19:rejeição24→pedido21→rejeitor24negado403/membroorg22negado403→revisor29reabre200→nova sessão21recupera. Decisão original permanece.', 'Visual; filas/designação/competências institucionais, políticas de prazo e instância ativa; manter decisão original e nenhuma autoridade real inferida.'),
+ 'AUD-PROFILE-22':('SLA explicitamente unconfigured e due_at=null; preparação e tarefas continuam. Cliente não fixa prazo arbitrário.', 'Tarefas e contexto recuperados com política/prazo nulos, sem tolerância/ciclos máximos inventados.', 'Decisão concreta futura:qual política/versionamento de prazos,tolerância,ciclos e escalamento é aprovada? Motor/publicação de parâmetros pendentes; não bloqueia preparação.'),
+ 'AUD-PROFILE-23':('Auditoria existente recupera atores, razões, estados/versões/gates/hash e tarefas/recurso; razões de edição preservadas no histórico cifrado.', 'Eventos workflow_submit/request_correction/review_gate/approve/publish/request_revision/suspend/appeal_reopen e revogações temporárias; nenhuma credencial/OTP/cookie exportados.', 'Visual de filtros/exportações e comparação detalhada; auditabilidade de operações futuras ainda não implementadas.'),
+ 'AUD-PROFILE-25':('Editor declarativo comum/especializado, escolha de referências/recursos; ações após submissão abrem /view, edição privada por link autorizado; fila/estado/título privados distinguem ficha pública.', 'PropsAPI e assetsQA:CRUD/ações/gates/prévia/tarefas; teste filtro necessidades/título privado; aprovação/pub com confirmação atual. NomePromotor QA — conta sintética21.', 'Nenhum clique/render observado:dashboard→contratos/erros→workflow→recuperação ainda exige navegador; geometrias/parcela e objetos sem editor completo permanecem abertos.'),
+ 'AUD-PROFILE-28':('Contrato canónico derivado do mesmo schema/condições normativas, sem alterar silenciosamente enums/IDs. Núcleo reutilizado, bindings/contactos/resources, submissão estrita e draft parcial.', '10drafts recuperados,6contratos completos estruturalmente aceites/4bloqueados por perfil;6verificados novamente no snapshot atual. Source.json false é histórico da extração, runtime rastreado no relatório.', 'Semântica §25/objetos opacos, Response integral, grillas específicas e quatro perfis aprovados; visual, publicação de todos os contratos com dados/provas aplicáveis ainda não demonstrada.'),
+ 'AUD-PROFILE-30':('PromotorQA21 claramente identificado, tipos autorizados por pedido/decisão independente. Validador24 reatribuído explicitamente, Publicador25 e instância sintética29 separados.', 'NormalFortify/MFA na18097; cenário18,19 e recuperação dos10drafts; negar self/multirole e revogar permissões temporárias. Não escolher titulares/responsáveis reais.', 'C37 e visual por cada perfil; novos processos/contratos ainda não cobertos. QA não equivale à instalação ativa.'),
+ 'AUD-PROFILE-31':('Código/Composer3novos pacotes, assets exclusivosQA, guardas e migrações existentes; recursos030000/profiles040000 precedem disponibilização das flags. Novos contratos não criam tabelas próprias.', 'AtivoREADONLY:020000sim/030000não/040000não/flagsfalse/0geom; QA393privadas,18conjuntosoriginais preservados/MFA18intacto/manifativo753... .', 'Aceitação visual, fechar editores/gates prioritários e fixar candidata; mecanismo040000ativo/authedbootstrap ainda não completo; renovarbackup/restauro dessa revisão, sem repetir instalações nem importar fixtures sintéticas.'),
+}
+for row in rows:
+ if row['ID'] in updates:
+ implementation,evidence,gap=updates[row['ID']]
+ row['Estado']='parcial'
+ append(row,'Implementação encontrada',implementation)
+ append(row,'Evidência funcional',evidence+' '+common)
+ append(row,'Lacuna',gap)
+ append(row,'Disponibilidade ativa','Leitura ativa10/10: PostgreSQLinvestemoz:5432READONLY;020000instalada;030000/040000ausentes;flagsdashboard/especializados/perfisfalse. Lote instalado e demonstrado apenasQA18097;zeroescritasativas,393geometrias privadasQA/0ativas. Não confundir código preparado,QA e instalação ativa.')
+ append(row,'Dependência','Continuar componentes canónicos/workflow/tarefas existentes; seis categorias estruturais disponíveisQA, quatro dependem de perfil modular versionado aprovado. Visual/C37, semântica/editor e políticas reais mantêm-se abertos conforme lacuna. Não requer integração externa para preparação interna.')
+ append(row,'API',evidence)
+ append(row,'Gravação','Persistência QA em opportunities/management_draft/workflow_context, coleções documentais/territoriais existentes, tasks/audit_events. IDs/originais/histórico conservados.')
+ append(row,'Recuperação','Nova sessão Fortify/MFA recupera payloads/recurso/estado, paísMZ/localização/documentos por IDs. Provas atuais identificadas por caso, sem usar contagem global como substituto.')
+ append(row,'Interface','Código e assetsQA984244d5dd9ece719d5c2d2ab852a6019aae8f728dab654c5a8bd6e75adec5a8; props/mensagens/ações demonstradasHTTP. Render/cliques pendentes; C37 permanece aberto.')
+ append(row,'Resultado apresentado','Resultados disponíveis nas respostasQA; aceitação visual e funcionalidade ativa permanecem separadas.')
+ elif row['ID'] in ['AUD-DASH-01','AUD-GEO-03','AUD-COUNTRY-01','AUD-STATS-01']:
+ append(row,'Evidência funcional','Consumidor oportunidades:Promotor21, contrato/localizaçãoMZ/documentos/refs recuperados por categoria; APIprivateboundaries existente. Não encerra países/origem/estatísticas por outros formulários, 188lacunas cartográficas nem render de mapas. '+common)
+ if row['ID'] == 'AUD-PROFILE-23':
+ row['Lacuna'] += ' Composer audit apontou dois avisos preexistentes em league/commonmark (GHSA-97jj-33gv-5xf9 e GHSA-3q6v-r5mr-hxv8); confirmar consumidores/configuração e corrigir emQA. Prova privada workflow-composer-audit.json; não são dos três pacotes Opis novos.'
+protected=['ID','Pedido/trecho','Fonte/ocorrências','Critério de aceitação','Versões divergentes','IDs das linhas de origem','Quantidade de linhas de origem','Critérios e versões por origem (JSON)']
+assert all(all(r[k]==before[r['ID']][k] for k in protected) for r in rows)
+with MATRIX.open('w',encoding='utf-8-sig',newline='') as f:
+ writer=csv.DictWriter(f,fieldnames=fields);writer.writeheader();writer.writerows(rows)
+origins=[item for r in rows for item in json.loads(r['Critérios e versões por origem (JSON)'])]
+assert len(origins)==6838
+counts=json.loads((PRIVATE/'contagens-requisitos.json').read_text())
+states=collections.defaultdict(lambda:{'requisitos':0,'linhas_origem':0})
+for row in rows:
+ states[row['Estado']]['requisitos']+=1;states[row['Estado']]['linhas_origem']+=int(row['Quantidade de linhas de origem'])
+counts.update({'requisitos':len(rows),'linhas_matriz':len(rows),'linhas_origem':len(origins),'por_estado':dict(states),
+ 'metodo':'Mesma matriz: 3.354 requisitos e 5.830 referências anteriores preservados; 32 requisitos verificáveis de perfis, 1.001 referências documentais e sete pedidos diretos. O incremento de workflow mantém requisitos parciais; não encerra aceitação visual nem contratos incompletos.',
+ 'conservation_sha256':hashlib.sha256(json.dumps(origins,ensure_ascii=False,sort_keys=True,separators=(',',':')).encode()).hexdigest(),
+ 'browser_current_version_verified':False,'workflow_updated_at':datetime.now(timezone.utc).isoformat()})
+(PRIVATE/'contagens-requisitos.json').write_text(json.dumps(counts,ensure_ascii=False,indent=2),encoding='utf-8')
+print(json.dumps({'requirements':len(rows),'source_occurrences':len(origins),'updated':list(updates),'states':dict(states),'active_writes':0},ensure_ascii=False))
+
+# Newer semantic evidence takes precedence over dated workflow claims.
+semantic = PRIVATE / 'opportunity-semantic-publication-http-qa.json'
+if semantic.exists() and json.loads(semantic.read_text()).get('result') == 'passed':
+ import runpy
+ runpy.run_path(str(ROOT / 'tools/portal-audit-semantic-update.py'), run_name='__main__')
diff --git a/tools/portal-dashboard-active-readonly.php b/tools/portal-dashboard-active-readonly.php
new file mode 100644
index 00000000..25846a48
--- /dev/null
+++ b/tools/portal-dashboard-active-readonly.php
@@ -0,0 +1,66 @@
+bootstrap($app);
+(new LoadConfiguration)->bootstrap($app);
+$config = $app->make('config');
+$connection = $config->get('database.connections.'.$config->get('database.default'));
+if (($connection['driver'] ?? null) !== 'pgsql' || ! empty($connection['url'])) {
+ throw new RuntimeException('Explicit PostgreSQL configuration required for read-only diagnosis.');
+}
+$pdo = new PDO('pgsql:host='.$connection['host'].';port='.$connection['port'].';dbname='.$connection['database'], $connection['username'], $connection['password'], [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
+$pdo->exec('BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY');
+try {
+ $identity = $pdo->query("SELECT current_database() AS database,inet_server_port() AS port,current_setting('transaction_read_only') AS read_only")->fetch(PDO::FETCH_ASSOC);
+ $managers = $config->get('portal.managers', []);
+ $accounts = [];
+ foreach ($pdo->query('SELECT id,email,email_verified_at FROM users ORDER BY id') as $user) {
+ $listed = in_array(strtolower($user['email']), $managers, true);
+ if ($listed || in_array((int) $user['id'], [13, 18], true)) {
+ $accounts[] = ['id' => (int) $user['id'], 'listed_manager' => $listed, 'email_verified' => $user['email_verified_at'] !== null, 'manage_portal' => $listed && $user['email_verified_at'] !== null];
+ }
+ }
+ $columns = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_schema='public' AND table_name='opportunities'")->fetchAll(PDO::FETCH_COLUMN);
+ $migrations = $pdo->query("SELECT migration FROM migrations WHERE migration LIKE '%opportunity_management%' OR migration LIKE '%opportunity_resources%' OR migration LIKE '%prepare_investor_path%' OR migration LIKE '%internal_virtual_desk%' OR migration LIKE '%extend_desk_investor_guidance%'")->fetchAll(PDO::FETCH_COLUMN);
+ $counts = $pdo->query('SELECT status,count(*) AS total FROM opportunities WHERE deleted_at IS NULL GROUP BY status ORDER BY status')->fetchAll(PDO::FETCH_ASSOC);
+ $resourcesInstalled = $pdo->query("SELECT to_regclass('public.opportunity_images') IS NOT NULL")->fetchColumn();
+ $profilesInstalled = $pdo->query("SELECT to_regclass('public.portal_role_assignments') IS NOT NULL")->fetchColumn();
+ $pathInstalled = $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='investor_journeys' AND column_name='path_definition_id')")->fetchColumn();
+ $pathDetails = ['migration' => '2026_10_09_190000_prepare_investor_path', 'ledger' => in_array('2026_10_09_190000_prepare_investor_path', $migrations, true),
+ 'journey_path_definition_column' => (bool) $pathInstalled,
+ 'step_path_detail_column' => (bool) $pdo->query("SELECT EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema='public' AND table_name='journey_steps' AND column_name='path_detail')")->fetchColumn(),
+ 'definitions' => $pdo->query("SELECT id,status,md5(schema_snapshot::text) AS snapshot_md5 FROM questionnaire_versions WHERE code='investor-path-19'")->fetchAll(PDO::FETCH_ASSOC)];
+ $geometryTable = $pdo->query("SELECT to_regclass('public.geo_geometries') IS NOT NULL")->fetchColumn();
+ $geometryCount = $geometryTable ? (int) $pdo->query('SELECT count(*) FROM geo_geometries WHERE deleted_at IS NULL')->fetchColumn() : null;
+} finally {
+ $pdo->exec('ROLLBACK');
+}
+$manifestPath = $root.'/public/build/manifest.json';
+$manifest = json_decode(file_get_contents($manifestPath), true, 512, JSON_THROW_ON_ERROR);
+$assets = [];
+foreach (['resources/js/app.tsx', 'resources/js/pages/dashboard.tsx', 'resources/js/pages/management/opportunities.tsx', 'resources/js/pages/management/opportunity-draft.tsx'] as $entry) {
+ $file = $manifest[$entry]['file'] ?? null;
+ $bytes = $file ? file_get_contents($root.'/public/build/'.$file) : '';
+ $assets[$entry] = ['file' => $file, 'sha256' => hash('sha256', $bytes), 'management_label' => str_contains($bytes, 'Gestão de Oportunidades'), 'new_label' => str_contains($bytes, 'Nova oportunidade'), 'old_create_label' => str_contains($bytes, 'Criar oportunidade')];
+}
+$proof = ['captured_at' => gmdate('c'), 'identity' => $identity, 'configured_app_url' => $config->get('app.url'), 'config_cached' => $app->configurationIsCached(),
+ 'routes_cached' => is_file($app->getCachedRoutesPath()), 'public_hot_present' => is_file($root.'/public/hot'), 'manager_configuration_count' => count($managers), 'accounts' => $accounts,
+ 'management_installed' => in_array('management_version', $columns, true), 'resource_extension_installed' => (bool) $resourcesInstalled, 'dashboard_increment_enabled' => (bool) $config->get('portal.opportunity_dashboard_access_enabled'), 'migrations' => $migrations, 'opportunities' => $counts,
+ 'investor_path_installed' => (bool) $pathInstalled, 'path_190000_evidence' => $pathDetails, 'active_geometry_count' => $geometryCount, 'specialized_increment_enabled' => (bool) $config->get('portal.opportunity_specialized_drafts_enabled'),
+ 'profile_authorization_installed' => (bool) $profilesInstalled, 'profile_access_enabled' => (bool) $config->get('portal.profile_access_enabled'),
+ 'session_configuration' => array_intersect_key($config->get('session'), array_flip(['driver', 'cookie', 'domain', 'path', 'secure', 'same_site'])),
+ 'manifest_sha256' => hash_file('sha256', $manifestPath), 'assets' => $assets, 'current_browser_actor_known' => false, 'active_writes' => 0];
+$dir = $root.'/storage/app/private/investmoz-v2/portal-audit';
+$path = $dir.'/dashboard-active-readonly.json';
+if (is_file($path)) {
+ copy($path, $dir.'/dashboard-active-readonly-'.gmdate('Ymd_His').'.json');
+}
+file_put_contents($path, json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-dashboard-navigation-check.mjs b/tools/portal-dashboard-navigation-check.mjs
new file mode 100644
index 00000000..d9bc31bc
--- /dev/null
+++ b/tools/portal-dashboard-navigation-check.mjs
@@ -0,0 +1,24 @@
+import assert from 'node:assert/strict';
+import { writeFileSync } from 'node:fs';
+import { portalNavigation } from '../resources/js/lib/portal-navigation.ts';
+
+const access = { installed: true, manage: { label: 'Gestão de Oportunidades', href: '/management/opportunities' }, create: { label: 'Nova oportunidade', href: '/management/opportunities/create' }, installationHref: '/management/opportunity-management-install' };
+const flatten = (items) => items.flatMap(item => [item, ...flatten(item.children ?? [])]);
+const manager = flatten(portalNavigation({ authenticated: true, manager: true, opportunityManagement: access }));
+assert.equal(manager.find(item => item.id === 'dashboard').href, '/dashboard');
+assert.equal(manager.find(item => item.id === 'dossiers').href, '/investidor');
+assert.equal(manager.filter(item => item.id === 'manage-opportunities').length, 1);
+assert.equal(manager.find(item => item.id === 'manage-opportunities').label, 'Gestão de Oportunidades');
+assert.equal(manager.find(item => item.id === 'create-opportunity').label, 'Nova oportunidade');
+const investor = flatten(portalNavigation({ authenticated: true, manager: false, opportunityManagement: access }));
+assert.equal(investor.find(item => item.id === 'dashboard').href, '/investidor');
+assert.equal(investor.some(item => item.id === 'manage-opportunities' || item.id === 'create-opportunity'), false);
+const disabled = flatten(portalNavigation({ authenticated: true, manager: true }));
+assert.equal(disabled.find(item => item.id === 'dashboard').href, '/investidor');
+assert.equal(disabled.find(item => item.id === 'manage-opportunities').label, 'Oportunidades');
+assert.equal(disabled.some(item => item.id === 'create-opportunity'), false);
+const pending = flatten(portalNavigation({ authenticated: true, manager: true, opportunityManagement: { ...access, installed: false } }));
+assert.equal(pending.some(item => item.id === 'create-opportunity'), false);
+const proof = { captured_at: new Date().toISOString(), manager_dashboard: '/dashboard', private_dossiers_preserved: '/investidor', management_destinations: 2, duplicate_management_items: 0, investor_denied: true, disabled_configuration_compatible: true, missing_installation_not_presented_as_installed: true, browser_visual_observed: false };
+writeFileSync(new URL('../storage/app/private/investmoz-v2/portal-audit/dashboard-navigation-catalogue-qa.json', import.meta.url), JSON.stringify(proof, null, 2));
+process.stdout.write(JSON.stringify(proof));
diff --git a/tools/portal-dashboard-opportunities-http-qa.py b/tools/portal-dashboard-opportunities-http-qa.py
new file mode 100644
index 00000000..e6b82846
--- /dev/null
+++ b/tools/portal-dashboard-opportunities-http-qa.py
@@ -0,0 +1,235 @@
+"""Follow dashboard destinations on the existing guarded QA server. No visual claim."""
+import base64
+import hashlib
+import hmac
+import http.cookiejar
+import json
+import re
+import struct
+import subprocess
+import sys
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+import uuid
+from datetime import datetime, timezone
+from pathlib import Path
+
+root = Path(__file__).resolve().parent.parent
+sys.stdout.reconfigure(encoding='utf-8')
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+php = Path.home() / '.config/investmoz/php-8.5.11/php.exe'
+target = json.loads((private.parent / 'opportunity-resources-backup-proof.json').read_text(encoding='utf-8-sig'))['restored_target']
+assert re.fullmatch(r'desk_restore_\d{8}_\d{6}_test', target['database']) and int(target['port']) == 55441
+expected = target['database'] + ':55441'
+manifest_path = root / 'public/build-qa-opportunities/manifest.json'
+manifest = json.loads(manifest_path.read_text(encoding='utf-8'))
+version = subprocess.check_output([str(php), '-r', "echo hash_file('xxh128','public/build-qa-opportunities/manifest.json');"], cwd=root, text=True).strip()
+actors = json.loads((private / 'resource-http-actors-private.json').read_text(encoding='utf-8-sig'))
+events = []
+
+
+def snapshot():
+ return json.loads(subprocess.check_output([str(php), 'tools/portal-dashboard-qa-snapshot.php'], cwd=root, text=True))
+
+
+def new_session():
+ global jar, opener
+ jar = http.cookiejar.CookieJar()
+ opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
+
+
+def call(method, path, data=None, status=200, inertia=False, raw=False):
+ assert path.startswith('/') and not path.startswith('//')
+ headers = {'Accept': 'application/json' if inertia or data is not None else 'text/html', 'Content-Type': 'application/json'}
+ for cookie in jar:
+ if cookie.name == 'XSRF-TOKEN':
+ headers['X-XSRF-TOKEN'] = urllib.parse.unquote(cookie.value)
+ if inertia:
+ headers.update({'X-Inertia': 'true', 'X-Inertia-Version': version})
+ request = urllib.request.Request('http://127.0.0.1:18097' + path, data=None if data is None else json.dumps(data).encode(), headers=headers, method=method)
+ try:
+ response = opener.open(request)
+ except urllib.error.HTTPError as error:
+ response = error
+ assert response.headers.get('X-Investmoz-QA-Target') == expected, 'QA header mismatch; refused'
+ body = response.read()
+ assert response.status == status, f'{method} {path.split("?")[0]}: expected {status}, observed {response.status}; body withheld'
+ events.append({'method': method, 'path': path.split('?')[0], 'status': response.status, 'qa_target_verified': True})
+ return body if raw else json.loads(body) if body else None
+
+
+def login(role):
+ call('GET', '/login', raw=True)
+ account = actors[role]
+ result = call('POST', '/login', {k: account[k] for k in ['email', 'password']})
+ required = bool(result.get('two_factor'))
+ if required:
+ assert account['totp_secret']
+ digest = hmac.new(base64.b32decode(account['totp_secret']), struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ code = f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+ call('POST', '/two-factor-challenge', {'code': code}, status=204)
+ return required
+
+
+if '--report-access-only' in sys.argv:
+ before = snapshot()
+ new_session()
+ login('manager')
+ report = call('GET', '/qa-auditoria/pedidos-abertos', raw=True)
+ assert hashlib.sha256(report).hexdigest() == hashlib.sha256((private / 'pedidos-abertos.html').read_bytes()).hexdigest()
+ assert report.count(b'make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+config(['portal.managers' => ['opportunity-manager@example.invalid', 'geo-manager-qa@example.invalid']]);
+$db = DB::connection();
+$db->beginTransaction();
+$db->statement('SET TRANSACTION READ ONLY');
+try {
+ $proof = ['target' => $target, 'tables' => [], 'opportunities' => [], 'accounts' => [], 'active_writes' => 0];
+ foreach (['opportunity_projects', 'opportunity_clusters', 'opportunity_images', 'opportunity_documents', 'opportunity_locations', 'documents', 'desk_cases', 'desk_requests', 'desk_documents', 'investor_journeys', 'journey_steps', 'tasks', 'questionnaire_versions', 'geo_locations', 'geo_geometries'] as $table) {
+ if (! Schema::hasTable($table)) {
+ continue;
+ }
+ $rows = $db->select('SELECT row_to_json(t)::text AS row FROM "'.$table.'" t ORDER BY row_to_json(t)::text');
+ $proof['tables'][$table] = ['rows' => count($rows), 'sha256' => hash('sha256', implode("\n", array_column($rows, 'row')))];
+ }
+ foreach ($db->select('SELECT id,row_to_json(t)::text AS row FROM opportunities t ORDER BY id') as $row) {
+ $proof['opportunities'][$row->id] = hash('sha256', $row->row);
+ }
+ $proof['published'] = Opportunity::published()->count();
+ foreach (User::whereIn('email', config('portal.managers'))->orWhereIn('id', [13, 18])->get() as $user) {
+ $proof['accounts'][] = ['id' => $user->id, 'manage_portal' => $user->can('manage-portal'), 'email_verified' => $user->hasVerifiedEmail(), 'mfa_configured' => (bool) $user->two_factor_secret];
+ }
+ $proof['account18_sha256'] = hash('sha256', json_encode($db->table('users')->where('id', 18)->first(), JSON_THROW_ON_ERROR));
+} finally {
+ $db->rollBack();
+}
+echo json_encode($proof, JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-geo-crosswalk-http-qa.py b/tools/portal-geo-crosswalk-http-qa.py
new file mode 100644
index 00000000..5a024ad4
--- /dev/null
+++ b/tools/portal-geo-crosswalk-http-qa.py
@@ -0,0 +1,113 @@
+"""Authenticated requests to the guarded QA server; no UI acceptance or active writes."""
+import base64
+import hashlib
+import hmac
+import http.cookiejar
+import json
+import re
+import struct
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+import uuid
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+
+root = Path(__file__).resolve().parent.parent
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+backup = json.loads((private.parent / 'opportunity-resources-backup-proof.json').read_text(encoding='utf-8-sig'))
+target = backup['restored_target']
+assert backup['restore_verified'] and re.fullmatch(r'desk_restore_\d{8}_\d{6}_test', target['database']) and int(target['port']) == 55441
+expected = target['database'] + ':55441'
+events = []
+jar = http.cookiejar.CookieJar()
+opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
+
+
+def call(method, path, data=None, status=200, html=False):
+ assert path.startswith('/') and not path.startswith('//')
+ headers = {'Accept': 'text/html' if html else 'application/json', 'Content-Type': 'application/json'}
+ for cookie in jar:
+ if cookie.name == 'XSRF-TOKEN':
+ headers['X-XSRF-TOKEN'] = urllib.parse.unquote(cookie.value)
+ request = urllib.request.Request('http://127.0.0.1:18097' + path, headers=headers, data=None if data is None else json.dumps(data).encode(), method=method)
+ try:
+ response = opener.open(request)
+ except urllib.error.HTTPError as e:
+ response = e
+ assert response.headers.get('X-Investmoz-QA-Target') == expected
+ content = response.read()
+ assert response.status == status, f'{method} {path}: expected {status}, observed {response.status}; response body withheld'
+ events.append({'method': method, 'url': path, 'status': response.status, 'qa_target_verified': True})
+ return None if html or not content else json.loads(content)
+
+
+call('GET', '/login', html=True)
+credentials = json.loads((private / 'i0-qa-actor-private.json').read_text(encoding='utf-8-sig'))
+login = call('POST', '/login', {k: credentials[k] for k in ['email', 'password']})
+if login.get('two_factor'):
+ secret = base64.b32decode(credentials['totp_secret'])
+ digest = hmac.new(secret, struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ code = f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+ call('POST', '/two-factor-challenge', {'code': code}, status=204)
+
+plans = []
+results = []
+apply = '--apply' in sys.argv
+verify_new = '--verify-new' in sys.argv
+assert not (apply and verify_new), 'Verification must not apply another batch.'
+for level in [1, 2, 3]:
+ plan = call('GET', f'/management/territory-geometry-import?level={level}')
+ plans.append(plan)
+ assert plan['expected'] == {1: 11, 2: 159, 3: 411}[level]
+ if not apply:
+ continue
+ assert plan['scan_ready'] and not any('conflict' in r['status'] or r['status'] == 'invalid_geometry' for r in plan['rows'])
+ data = {'level': level, 'hash': plan['hash'], 'idempotency_key': str(uuid.uuid4()), 'reason': 'Correspondências explícitas Maputo e descendentes sob os pais aceites, exclusivamente em QA', 'confirm': True}
+ result = call('POST', '/management/territory-geometry-import', data)
+ assert not result['published'] and result['resolved'] == plan['resolved']
+ assert call('POST', '/management/territory-geometry-import', data) == result
+ updated = call('GET', f'/management/territory-geometry-import?level={level}')
+ assert all(r['status'] == 'reuse' for r in updated['rows'] if r['location_id'])
+ results.append(result)
+# Recovery through the actual endpoints used by the hierarchy fields and map component.
+consumers = []
+locations_to_verify = []
+for plan in plans:
+ for row in plan['rows']:
+ if row['status'] != 'insert' or not row['location_id'] or not apply:
+ continue
+ locations_to_verify.append(row['location_id'])
+if verify_new:
+ preservation = json.loads((private / 'geometry-crosswalk-preservation-qa.json').read_text(encoding='utf-8-sig'))
+ assert preservation['target'] == target and preservation['catalogue_preserved'] and preservation['original_geometries_preserved'] == 361
+ locations_to_verify = [g['location_id'] for g in preservation['new_geometries']]
+ assert len(locations_to_verify) == len(set(locations_to_verify)) == 32
+for location_id in locations_to_verify:
+ context = call('GET', '/management/territory-geometries?' + urllib.parse.urlencode({'territory_id': location_id}))
+ assert context['selected_geometry_available'] and any(a['selected_territory'] and a['territory_id'] == location_id for a in context['areas'])
+ consumers.append({'territory_id': location_id, 'selected_geometry_available_manager': True, 'areas': len(context['areas'])})
+province_name_recovery = []
+if verify_new:
+ for name in ['Maputo Província', 'Maputo Cidade']:
+ options = call('GET', '/api/v1/investment/territory-options?' + urllib.parse.urlencode({'type': 'province', 'page': 1, 'q': name}))
+ matches = [o for o in options['data'] if o['name'] == name]
+ assert len(matches) == 1 and not options.get('next_page_url')
+ assert matches[0]['id'] in locations_to_verify
+ province_name_recovery.append({'name': name, 'territory_id': matches[0]['id'], 'unique_exact_match': True})
+call('POST', '/logout', status=204)
+public_recovery = []
+if verify_new:
+ for location_id in locations_to_verify:
+ context = call('GET', '/api/v1/investment/territory-geometries?' + urllib.parse.urlencode({'territory_id': location_id}))
+ assert not context['selected_geometry_available'] and context['areas'] == []
+ public_recovery.append({'territory_id': location_id, 'private_geometry_not_disclosed': True})
+proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'applied': apply, 'mfa_login_completed': bool(login.get('two_factor')), 'plans': plans, 'results': results, 'consumer_recovery': consumers, 'province_name_recovery': province_name_recovery, 'public_recovery': public_recovery, 'requests': events, 'interface_observed': False, 'active_writes': 0, 'published': False}
+destination = private / ('geometry-crosswalk-http-qa.json' if apply else 'geometry-crosswalk-consumers-http-qa.json' if verify_new else 'geometry-crosswalk-preview-qa.json')
+if destination.exists():
+ destination.rename(private / (destination.stem + '-' + datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') + '.json'))
+destination.write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'target': target, 'applied': apply, 'levels': [{'level': p['level'], 'expected': p['expected'], 'resolved': p['resolved'], 'pending': p['pending']} for p in plans], 'inserted': sum(r['inserted'] for r in results), 'reused': sum(r['reused'] for r in results), 'consumers': len(consumers), 'published': False, 'interface_observed': False, 'active_writes': 0}))
diff --git a/tools/portal-geo-crosswalk-v2-http-qa.py b/tools/portal-geo-crosswalk-v2-http-qa.py
new file mode 100644
index 00000000..e6b5d092
--- /dev/null
+++ b/tools/portal-geo-crosswalk-v2-http-qa.py
@@ -0,0 +1,113 @@
+"""Authenticated requests to the guarded QA server; no UI acceptance or active writes."""
+import base64
+import hashlib
+import hmac
+import http.cookiejar
+import json
+import re
+import struct
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+import uuid
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+
+root = Path(__file__).resolve().parent.parent
+private = root / 'storage/app/private/investmoz-v2/portal-audit'
+backup = json.loads((private.parent / 'opportunity-resources-backup-proof.json').read_text(encoding='utf-8-sig'))
+target = backup['restored_target']
+assert backup['restore_verified'] and re.fullmatch(r'desk_restore_\d{8}_\d{6}_test', target['database']) and int(target['port']) == 55441
+expected = target['database'] + ':55441'
+events = []
+jar = http.cookiejar.CookieJar()
+opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
+
+
+def call(method, path, data=None, status=200, html=False):
+ assert path.startswith('/') and not path.startswith('//')
+ headers = {'Accept': 'text/html' if html else 'application/json', 'Content-Type': 'application/json'}
+ for cookie in jar:
+ if cookie.name == 'XSRF-TOKEN':
+ headers['X-XSRF-TOKEN'] = urllib.parse.unquote(cookie.value)
+ request = urllib.request.Request('http://127.0.0.1:18097' + path, headers=headers, data=None if data is None else json.dumps(data).encode(), method=method)
+ try:
+ response = opener.open(request)
+ except urllib.error.HTTPError as e:
+ response = e
+ assert response.headers.get('X-Investmoz-QA-Target') == expected
+ content = response.read()
+ assert response.status == status, f'{method} {path}: expected {status}, observed {response.status}; response body withheld'
+ events.append({'method': method, 'url': path, 'status': response.status, 'qa_target_verified': True})
+ return None if html or not content else json.loads(content)
+
+
+call('GET', '/login', html=True)
+credentials = json.loads((private / 'i0-qa-actor-private.json').read_text(encoding='utf-8-sig'))
+login = call('POST', '/login', {k: credentials[k] for k in ['email', 'password']})
+if login.get('two_factor'):
+ secret = base64.b32decode(credentials['totp_secret'])
+ digest = hmac.new(secret, struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ code = f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+ call('POST', '/two-factor-challenge', {'code': code}, status=204)
+
+plans = []
+results = []
+apply = '--apply' in sys.argv
+verify_new = '--verify-new' in sys.argv
+assert not (apply and verify_new), 'Verification must not apply another batch.'
+for level in [1, 2, 3]:
+ plan = call('GET', f'/management/territory-geometry-import?level={level}')
+ plans.append(plan)
+ assert plan['expected'] == {1: 11, 2: 159, 3: 411}[level]
+ if not apply:
+ continue
+ assert plan['scan_ready'] and not any('conflict' in r['status'] or r['status'] == 'invalid_geometry' for r in plan['rows'])
+ data = {'level': level, 'hash': plan['hash'], 'idempotency_key': str(uuid.uuid4()), 'reason': 'Correspondências explícitas Maputo e descendentes sob os pais aceites, exclusivamente em QA', 'confirm': True}
+ result = call('POST', '/management/territory-geometry-import', data)
+ assert not result['published'] and result['resolved'] == plan['resolved']
+ assert call('POST', '/management/territory-geometry-import', data) == result
+ updated = call('GET', f'/management/territory-geometry-import?level={level}')
+ assert all(r['status'] == 'reuse' for r in updated['rows'] if r['location_id'])
+ results.append(result)
+# Recovery through the actual endpoints used by the hierarchy fields and map component.
+consumers = []
+locations_to_verify = []
+for plan in plans:
+ for row in plan['rows']:
+ if row['status'] != 'insert' or not row['location_id'] or not apply:
+ continue
+ locations_to_verify.append(row['location_id'])
+if verify_new:
+ preservation = json.loads((private / 'geometry-crosswalk-v2-preservation-qa.json').read_text(encoding='utf-8-sig'))
+ assert preservation['target'] == target and preservation['catalogue_preserved'] and preservation['original_geometries_preserved'] == 361
+ locations_to_verify = [g['location_id'] for g in preservation['new_geometries']]
+ assert len(locations_to_verify) == len(set(locations_to_verify)) == 47
+for location_id in locations_to_verify:
+ context = call('GET', '/management/territory-geometries?' + urllib.parse.urlencode({'territory_id': location_id}))
+ assert context['selected_geometry_available'] and any(a['selected_territory'] and a['territory_id'] == location_id for a in context['areas'])
+ consumers.append({'territory_id': location_id, 'selected_geometry_available_manager': True, 'areas': len(context['areas'])})
+province_name_recovery = []
+if verify_new:
+ for name in ['Maputo Província', 'Maputo Cidade']:
+ options = call('GET', '/api/v1/investment/territory-options?' + urllib.parse.urlencode({'type': 'province', 'page': 1, 'q': name}))
+ matches = [o for o in options['data'] if o['name'] == name]
+ assert len(matches) == 1 and not options.get('next_page_url')
+ assert matches[0]['id'] in locations_to_verify
+ province_name_recovery.append({'name': name, 'territory_id': matches[0]['id'], 'unique_exact_match': True})
+call('POST', '/logout', status=204)
+public_recovery = []
+if verify_new:
+ for location_id in locations_to_verify:
+ context = call('GET', '/api/v1/investment/territory-geometries?' + urllib.parse.urlencode({'territory_id': location_id}))
+ assert not context['selected_geometry_available'] and context['areas'] == []
+ public_recovery.append({'territory_id': location_id, 'private_geometry_not_disclosed': True})
+proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'applied': apply, 'mfa_login_completed': bool(login.get('two_factor')), 'plans': plans, 'results': results, 'consumer_recovery': consumers, 'province_name_recovery': province_name_recovery, 'public_recovery': public_recovery, 'requests': events, 'interface_observed': False, 'active_writes': 0, 'published': False}
+destination = private / ('geometry-crosswalk-v2-http-qa.json' if apply else 'geometry-crosswalk-v2-consumers-http-qa.json' if verify_new else 'geometry-crosswalk-v2-preview-qa.json')
+if destination.exists():
+ destination.rename(private / (destination.stem + '-' + datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') + '.json'))
+destination.write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'target': target, 'applied': apply, 'levels': [{'level': p['level'], 'expected': p['expected'], 'resolved': p['resolved'], 'pending': p['pending']} for p in plans], 'inserted': sum(r['inserted'] for r in results), 'reused': sum(r['reused'] for r in results), 'consumers': len(consumers), 'published': False, 'interface_observed': False, 'active_writes': 0}))
diff --git a/tools/portal-geo-reconciliation-qa.php b/tools/portal-geo-reconciliation-qa.php
new file mode 100644
index 00000000..3c237e58
--- /dev/null
+++ b/tools/portal-geo-reconciliation-qa.php
@@ -0,0 +1,97 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+if (($argv[1] ?? '') === 'preview') {
+ config(['geometry-import.enabled' => true, 'portal.managers' => ['geo-manager-qa@example.invalid']]);
+ $actor = User::where('email', 'geo-manager-qa@example.invalid')->firstOrFail();
+ $plans = DB::transaction(function () use ($actor) {
+ DB::statement('SET TRANSACTION READ ONLY');
+
+ return array_map(fn ($level) => app(TerritoryGeometryImport::class)->preview($actor, $level), [1, 2, 3]);
+ });
+ foreach ($plans as $plan) {
+ echo json_encode(['level' => $plan['level'], 'expected' => $plan['expected'], 'resolved' => $plan['resolved'], 'pending' => $plan['pending'], 'scan_ready' => $plan['scan_ready'],
+ 'errors' => array_values(array_filter($plan['rows'], fn ($row) => str_contains($row['status'], 'conflict') || $row['status'] === 'invalid_geometry'))], JSON_THROW_ON_ERROR).PHP_EOL;
+ }
+ exit;
+}
+$snapshot = DB::transaction(function () {
+ DB::statement('SET TRANSACTION READ ONLY');
+
+ return [
+ 'locations' => DB::table('geo_locations')->orderBy('location_type')->orderBy('name')->get(),
+ 'geometries' => DB::table('geo_geometries')->selectRaw("id,external_id,geo_location_id,source_system,properties,data_classification,version_no,deleted_at,encode(ST_AsEWKB(geom),'hex') as geometry_bytes")->orderBy('id')->get(),
+ ];
+});
+$snapshot['target'] = $target;
+$snapshot['captured_at'] = gmdate('c');
+$snapshot['catalogue_hash'] = hash('sha256', json_encode($snapshot['locations'], JSON_THROW_ON_ERROR));
+$snapshot['geometries_hash'] = hash('sha256', json_encode($snapshot['geometries'], JSON_THROW_ON_ERROR));
+$snapshot['active_writes'] = 0;
+if (($argv[1] ?? '') === 'verify') {
+ $baseline = json_decode(file_get_contents(storage_path('app/private/investmoz-v2/portal-audit/geometry-reconciliation-baseline.json')), true, 512, JSON_THROW_ON_ERROR);
+ $oldLocations = json_encode($baseline['locations'], JSON_THROW_ON_ERROR);
+ $locationsPreserved = hash_equals(hash('sha256', $oldLocations), $snapshot['catalogue_hash']);
+ $current = [];
+ foreach ($snapshot['geometries'] as $row) {
+ $current[$row->id] = (array) $row;
+ }
+ foreach ($baseline['geometries'] as $row) {
+ if (! isset($current[$row['id']]) || json_encode($row, JSON_THROW_ON_ERROR) !== json_encode($current[$row['id']], JSON_THROW_ON_ERROR)) {
+ throw new RuntimeException('An original QA geometry changed; preservation proof refused.');
+ }
+ unset($current[$row['id']]);
+ }
+ if (! $locationsPreserved) {
+ throw new RuntimeException('The existing QA catalogue changed; preservation proof refused.');
+ }
+ $locationTypes = [];
+ foreach ($snapshot['locations'] as $row) {
+ $locationTypes[$row->id] = $row->location_type;
+ }
+ $new = [];
+ $counts = [];
+ foreach ($snapshot['geometries'] as $row) {
+ if (! $row->deleted_at) {
+ $type = $locationTypes[$row->geo_location_id];
+ $counts[$type] = ($counts[$type] ?? 0) + 1;
+ }
+ if (isset($current[$row->id])) {
+ $properties = json_decode($row->properties, true, 512, JSON_THROW_ON_ERROR);
+ if ($row->data_classification !== 'internal' || $row->deleted_at || ($properties['investment_site'] ?? null) !== false) {
+ throw new RuntimeException('Unexpected disclosure/lifecycle/purpose of new QA boundary.');
+ }
+ $new[] = ['id' => $row->id, 'location_id' => $row->geo_location_id, 'type' => $locationTypes[$row->geo_location_id], 'external_id' => $row->external_id, 'properties' => $properties];
+ }
+ }
+ $imports = DB::transaction(function () {
+ DB::statement('SET TRANSACTION READ ONLY');
+
+ return DB::table('audit_events')->where('source_system', 'geometry-import')->where('action', 'geometry_import_applied')->orderBy('occurred_at')->get(['entity_id', 'actor_user_id', 'occurred_at', 'after_data']);
+ });
+ $proof = ['captured_at' => gmdate('c'), 'target' => $target, 'catalogue_count' => count($snapshot['locations']), 'catalogue_preserved' => true,
+ 'catalogue_hash' => $snapshot['catalogue_hash'], 'original_geometries_preserved' => count($baseline['geometries']), 'new_geometries' => $new,
+ 'geometries_by_level' => $counts, 'total_active' => array_sum($counts), 'authenticated_import_events' => $imports,
+ 'published' => false, 'read_only_verification' => true, 'interface_observed' => false, 'active_writes' => 0];
+ file_put_contents(storage_path('app/private/investmoz-v2/portal-audit/geometry-crosswalk-preservation-qa.json'), json_encode($proof, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR));
+ echo json_encode(['target' => $target, 'catalogue_preserved' => true, 'original_geometries_preserved' => count($baseline['geometries']), 'new_geometries' => count($new), 'counts' => $counts, 'total' => array_sum($counts), 'published' => false, 'active_writes' => 0], JSON_THROW_ON_ERROR).PHP_EOL;
+ exit;
+}
+$file = storage_path('app/private/investmoz-v2/portal-audit/geometry-reconciliation-baseline.json');
+if (is_file($file)) {
+ $file = dirname($file).'/geometry-reconciliation-snapshot-'.gmdate('Ymd_His').'.json';
+}
+file_put_contents($file, json_encode($snapshot, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR));
+echo json_encode(['target' => $target, 'locations' => count($snapshot['locations']), 'geometries' => count($snapshot['geometries']), 'catalogue_hash' => $snapshot['catalogue_hash'], 'active_writes' => 0], JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-profile-installation-backup-qa.php b/tools/portal-profile-installation-backup-qa.php
new file mode 100644
index 00000000..709379be
--- /dev/null
+++ b/tools/portal-profile-installation-backup-qa.php
@@ -0,0 +1,104 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$code = app(PortalProfileInstallation::class)->fingerprint();
+$tests = json_decode(file_get_contents(storage_path('app/private/investmoz-v2/portal-audit/profile-installation-checks-qa.json')), true, 512, JSON_THROW_ON_ERROR);
+throw_unless(($tests['result'] ?? null) === 'passed' && ($tests['code_hash'] ?? null) === $code, RuntimeException::class, 'Current installation QA checks required.');
+$c = DB::connection()->getConfig();
+throw_unless(in_array($c['url'] ?? null, [null, ''], true) && str_ends_with($c['database'], '_test') && (int) $c['port'] === 55441 && $c['host'] === '127.0.0.1', RuntimeException::class, 'QA connection refused.');
+$source = DB::connection()->getPdo();
+$source->exec('BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY');
+$restoreName = 'profile_restore_'.gmdate('Ymd_His').'_test';
+$directory = storage_path('app/private/investmoz-v2/portal-profile-installation/'.$restoreName);
+mkdir($directory, 0700, true);
+$dump = $directory.'/database.dump';
+$run = function (array $args, string $password): void {
+ $process = new Process($args, null, ['PGPASSWORD' => $password]);
+ $process->setTimeout(300);
+ $process->run();
+ throw_unless($process->isSuccessful(), RuntimeException::class, 'QA backup/restore command failed; output withheld.');
+};
+$bin = 'C:/Program Files/PostgreSQL/17/bin/';
+$snapshot = $source->query('SELECT pg_export_snapshot()')->fetchColumn();
+$run([$bin.'pg_dump.exe', '-h', $c['host'], '-p', '55441', '-U', $c['username'], '-d', $c['database'], '-Fc', '--snapshot='.$snapshot, '-f', $dump], $c['password'] ?? '');
+$maintenance = new PDO('pgsql:host=127.0.0.1;port=55441;dbname=postgres', 'postgres', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
+throw_unless((int) $maintenance->query('SELECT inet_server_port()')->fetchColumn() === 55441 && preg_match('/^profile_restore_\d{8}_\d{6}_test$/', $restoreName), RuntimeException::class, 'Restore target refused.');
+$maintenance->exec('CREATE DATABASE "'.$restoreName.'"');
+$run([$bin.'pg_restore.exe', '-h', '127.0.0.1', '-p', '55441', '-U', 'postgres', '-d', $restoreName, '--exit-on-error', '--no-owner', '--no-privileges', $dump], '');
+$restored = new PDO('pgsql:host=127.0.0.1;port=55441;dbname='.$restoreName, 'postgres', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
+$identity = $restored->query('SELECT current_database() AS database,inet_server_port() AS port')->fetch(PDO::FETCH_ASSOC);
+throw_unless($identity['database'] === $restoreName && (int) $identity['port'] === 55441, RuntimeException::class, 'Actual restore identity refused.');
+$restored->exec('BEGIN READ ONLY');
+$tableProof = [];
+foreach ($source->query("SELECT schemaname,tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema') ORDER BY schemaname,tablename")->fetchAll(PDO::FETCH_ASSOC) as $table) {
+ $name = '"'.str_replace('"', '""', $table['schemaname']).'"."'.str_replace('"', '""', $table['tablename']).'"';
+ $sql = 'SELECT row_to_json(t)::text FROM '.$name.' t ORDER BY row_to_json(t)::text';
+ $a = $source->query($sql)->fetchAll(PDO::FETCH_COLUMN);
+ $b = $restored->query($sql)->fetchAll(PDO::FETCH_COLUMN);
+ throw_unless($a === $b, RuntimeException::class, 'Restored table contents differ.');
+ $tableProof[$name] = ['count' => count($a), 'sha256' => hash('sha256', implode("\n", $a))];
+}
+$documents = $source->query('SELECT storage_key FROM documents WHERE storage_key IS NOT NULL')->fetchAll(PDO::FETCH_COLUMN);
+$source->exec('ROLLBACK');
+$restored->exec('ROLLBACK');
+$files = $directory.'/private-files.zip';
+$zip = new ZipArchive;
+throw_unless($zip->open($files, ZipArchive::CREATE | ZipArchive::EXCL) === true, RuntimeException::class, 'Private archive unavailable.');
+$root = realpath(storage_path('app/private'));
+$manifest = [];
+$missing = [];
+foreach (array_unique($documents) as $relative) {
+ $path = realpath(storage_path('app/private/'.$relative));
+ if ($path === false) {
+ $missing[] = $relative;
+
+ continue;
+ }
+ throw_unless(str_starts_with(strtolower($path), strtolower($root.DIRECTORY_SEPARATOR)), RuntimeException::class, 'Document outside private storage.');
+ $name = 'private/'.str_replace('\\', '/', $relative);
+ $zip->addFile($path, $name);
+ $manifest[$name] = hash_file('sha256', $path);
+}
+// Preserve the QA runtime/key, never the active .env. Archive remains private.
+$runtime = base_path('tools/portal-qa-environment.php');
+$zip->addFile($runtime, 'runtime/portal-qa-environment.php');
+$manifest['runtime/portal-qa-environment.php'] = hash_file('sha256', $runtime);
+$zip->close();
+$read = new ZipArchive;
+$read->open($files);
+$restoreFiles = $directory.'/files-restored';
+mkdir($restoreFiles, 0700, true);
+$restoreRoot = realpath($restoreFiles);
+throw_unless(str_starts_with(strtolower($restoreRoot), strtolower(realpath(storage_path('app/private/investmoz-v2/portal-profile-installation')).DIRECTORY_SEPARATOR)), RuntimeException::class, 'File restore root refused.');
+foreach ($manifest as $name => $hash) {
+ throw_unless(! str_contains($name, ':') && ! str_starts_with($name, '/') && ! array_intersect(explode('/', $name), ['.', '..']), RuntimeException::class, 'Archive member path refused.');
+ $bytes = $read->getFromName($name);
+ throw_unless(is_string($bytes) && hash('sha256', $bytes) === $hash, RuntimeException::class, 'Archived bytes differ.');
+ $destination = $restoreRoot.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $name);
+ if (! is_dir(dirname($destination))) {
+ mkdir(dirname($destination), 0700, true);
+ }
+ throw_unless(str_starts_with(strtolower(realpath(dirname($destination))), strtolower($restoreRoot.DIRECTORY_SEPARATOR)), RuntimeException::class, 'Resolved restore destination refused.');
+ file_put_contents($destination, $bytes);
+ throw_unless(hash_file('sha256', $destination) === $hash, RuntimeException::class, 'Restored file differs.');
+}
+$read->close();
+$proof = ['verified_at' => gmdate('c'), 'target' => $target, 'restored_target' => $identity, 'code_hash' => $code,
+ 'restore_verified' => true, 'files_verified' => $missing === [], 'files_restore_verified' => true, 'files_restore_root' => $restoreRoot, 'compatibility_verified' => true, 'qa_passed' => true,
+ 'dump_path' => $dump, 'dump_sha256' => hash_file('sha256', $dump), 'files_path' => $files, 'files_sha256' => hash_file('sha256', $files),
+ 'tables' => $tableProof, 'files' => $manifest, 'missing_document_files' => $missing, 'active_writes' => 0,
+ 'scope' => 'QA schema/data restore and archived byte recovery; not active backup, visual acceptance or recovery of lost MFA.', 'checks' => $tests];
+file_put_contents($directory.'/proof.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+file_put_contents(config('portal_profiles.proof_directory').'/readiness.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode(['target' => $target, 'restored_target' => $identity, 'restore_verified' => true, 'tables' => count($tableProof), 'files' => count($manifest), 'missing_files' => count($missing), 'ready_files' => $missing === [], 'active_writes' => 0], JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-profile-installation-checks-qa.py b/tools/portal-profile-installation-checks-qa.py
new file mode 100644
index 00000000..5d9796d9
--- /dev/null
+++ b/tools/portal-profile-installation-checks-qa.py
@@ -0,0 +1,34 @@
+"""Isolated tests plus frontend checks; never claim browser acceptance."""
+import json
+import subprocess
+import sys
+from datetime import datetime, timezone
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+PHP = 'C:/Users/macbook/.config/investmoz/php-8.5.11/php.exe'
+files = ['PortalProfileInstallationTest', 'OpportunityPublicationScopeTest', 'PortalProfileAccessTest', 'OpportunityCanonicalWorkflowTest', 'IndependentDocumentOperationsTest', 'TerritoryGeometryImportTest']
+if '--installer-only' in sys.argv:
+ previous = PRIVATE / 'profile-installation-checks-qa.json'
+ archive = PRIVATE / 'profile-installation-regression-qa.json'
+ if previous.exists() and not archive.exists():
+ archive.write_bytes(previous.read_bytes())
+ files = ['PortalProfileInstallationTest', 'OpportunityPublicationScopeTest']
+unit = subprocess.run([PHP, '-d', 'extension=C:/Users/macbook/.config/investmoz/php-8.5.11/ext/php_gd.dll', 'vendor/bin/phpunit', *['tests/Feature/' + f + '.php' for f in files], '--no-progress'], cwd=ROOT, capture_output=True)
+try:
+ tests = json.loads(unit.stdout.decode('utf-8-sig'))
+except Exception:
+ raise RuntimeError('Unit runner output was not a sanitized JSON receipt; output withheld')
+(PRIVATE / 'profile-installation-unit-qa.json').write_text(json.dumps(tests, ensure_ascii=False, indent=2), encoding='utf-8')
+assert unit.returncode == 0 and tests['result'] == 'passed' and tests.get('skipped', 0) == 0, 'QA tests failed; details retained privately'
+types = subprocess.run(['cmd', '/c', 'npm.cmd', 'run', 'types:check'], cwd=ROOT, capture_output=True)
+assert types.returncode == 0, 'TypeScript failed; output withheld'
+result = subprocess.run([PHP, 'tools/portal-profile-installation-status-qa.php'], cwd=ROOT, capture_output=True)
+assert result.returncode == 0, 'Guarded status failed; output withheld'
+status = json.loads(result.stdout.decode('utf-8-sig'))
+proof = {'result': 'passed', 'target': status['target'], 'code_hash': status['code_hash'], 'checked_at': datetime.now(timezone.utc).isoformat(),
+ 'tests': tests, 'types_passed': True, 'scope': ('Final installation rollback guard and publication scopes; preceding regression is separately dated' if '--installer-only' in sys.argv else 'Installation, scope labels, profile/canonical/document/cartographic regression') + '; interface not observed',
+ 'interface_observed': False, 'active_writes': 0}
+(PRIVATE / 'profile-installation-checks-qa.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'result': 'passed', 'tests': tests['tests'], 'assertions': tests['assertions'], 'types_passed': True, 'active_writes': 0}))
diff --git a/tools/portal-profile-installation-http-qa.py b/tools/portal-profile-installation-http-qa.py
new file mode 100644
index 00000000..a632fbf9
--- /dev/null
+++ b/tools/portal-profile-installation-http-qa.py
@@ -0,0 +1,48 @@
+"""Real authenticated no-op on an already used 040000 QA schema; no destructive reinstall."""
+import json
+import uuid
+from datetime import datetime, timezone
+from portal_profiles_http_session import Session, PRIVATE, EXPECTED, REASON, events
+
+proof = {'target': EXPECTED, 'started_at': datetime.now(timezone.utc).isoformat(), 'active_writes': 0, 'interface_observed': False}
+try:
+ holder = Session('super_first').login()
+ plan = holder.call('GET', '/management/profile-install')
+ proof['code_hash'] = plan['code_hash']
+ assert plan['installed'] and plan['consistent'] and plan['bootstrap']['initialized']
+ assert all(plan['dependencies'].values()) and plan['path_190000_installed']
+ data = {'hash': plan['hash'], 'confirm': True, 'idempotency_key': str(uuid.uuid4()), 'reason': REASON}
+ result = holder.call('POST', '/management/profile-install', data)
+ assert result['installed'] and not result['changed'] and not result['flags_changed']
+ assert holder.call('POST', '/management/profile-install', data) == result
+ holder.call('POST', '/management/profile-install', {**data, 'reason': REASON + ' changed'}, status=409)
+ fresh = Session('super_first').login()
+ recovered = fresh.call('GET', '/management/profile-install')
+ assert recovered['installed'] and recovered['bootstrap'] == plan['bootstrap']
+ for role in ['promoter', 'auditor', 'outsider']:
+ denied = Session(role).login()
+ denied.call('GET', '/management/profile-install', status=403)
+ denied.call('POST', '/management/profile-install', data, status=403)
+ fresh.call('POST', '/management/profile-install/bootstrap', {**data, 'hash': recovered['hash'], 'idempotency_key': str(uuid.uuid4()),
+ 'first_user_id': recovered['bootstrap']['holders'][0], 'second_user_id': recovered['bootstrap']['holders'][1]}, status=409)
+ promoter = Session('promoter').login()
+ source = json.loads((PRIVATE / 'opportunity-semantic-http-qa.json').read_text(encoding='utf-8-sig'))
+ labels = []
+ for category in ['investment_project', 'business_sale', 'land_rights']:
+ case = next(c for c in source['cases'] if c['category'] == category)
+ page = promoter.call('GET', f"/minhas-oportunidades/{case['id']}/view", inertia=True)['props']
+ labels.append({'id': case['id'], 'category': category, 'publication': page['publicationState'], 'working_state': page['workflowState']})
+ assert labels[0]['publication']['scope'] == 'restricted' and not labels[0]['publication']['public_catalog']
+ assert labels[1]['publication']['scope'] == 'public' and labels[1]['publication']['public_catalog']
+ assert labels[2]['publication']['scope'] == 'unpublished' and labels[2]['working_state'] == 'approved'
+ proof.update({'result': 'passed', 'ready': recovered['ready'], 'installed': True, 'changed': False, 'idempotency_verified': True,
+ 'new_session_recovery': True, 'denied_profiles': [21, 26, 23], 'existing_pair_unchanged': True, 'bootstrap_existing_pair': 409,
+ 'publication_labels': labels, 'cold_install_scope': 'Separate isolated HTTP feature tests; live QA schema is already in use and was not removed.'})
+except Exception as error:
+ proof.update({'result': 'failed', 'failure': str(error)})
+ raise
+finally:
+ proof['events'] = events
+ proof['completed_at'] = datetime.now(timezone.utc).isoformat()
+ (PRIVATE / 'profile-installation-http-qa.json').write_text(json.dumps(proof, ensure_ascii=False, indent=2), encoding='utf-8')
+print(json.dumps({'result': proof['result'], 'target': EXPECTED, 'installed': True, 'no_op': True, 'events': len(events), 'interface_observed': False, 'active_writes': 0}))
diff --git a/tools/portal-profile-installation-status-qa.php b/tools/portal-profile-installation-status-qa.php
new file mode 100644
index 00000000..8a19d26e
--- /dev/null
+++ b/tools/portal-profile-installation-status-qa.php
@@ -0,0 +1,23 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$proof = DB::transaction(function () use ($target) {
+ DB::statement('SET TRANSACTION READ ONLY');
+
+ return ['target' => $target, 'code_hash' => app(PortalProfileInstallation::class)->fingerprint(), 'captured_at' => gmdate('c'),
+ 'schema_installed' => DB::table('migrations')->where('migration', PortalProfileInstallation::MIGRATION)->exists(),
+ 'users' => DB::table('users')->count(), 'grants' => DB::table('portal_role_assignments')->count(),
+ 'pair_hash' => hash('sha256', json_encode(DB::table('portal_superuser_pair')->first(), JSON_THROW_ON_ERROR)),
+ 'active_manifest_sha256' => hash_file('sha256', public_path('build/manifest.json')), 'active_writes' => 0];
+});
+file_put_contents(storage_path('app/private/investmoz-v2/portal-audit/profile-installation-status-qa.json'), json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode($proof, JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-profiles-http-qa.py b/tools/portal-profiles-http-qa.py
new file mode 100644
index 00000000..582fa21a
--- /dev/null
+++ b/tools/portal-profiles-http-qa.py
@@ -0,0 +1,364 @@
+"""Profile acceptance through the guarded QA server. No credential/OTP/header output."""
+import base64
+import hashlib
+import hmac
+import http.cookiejar
+import json
+import struct
+import subprocess
+import sys
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+import uuid
+from datetime import datetime, timezone
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+ACTOR_FILE = PRIVATE / 'profiles-v1-actors-private.json'
+actors = json.loads(ACTOR_FILE.read_text(encoding='utf-8-sig'))
+organizations = json.loads((PRIVATE / 'profiles-v1-organizations-qa.json').read_text())
+baseline = json.loads((PRIVATE / 'profiles-v1-before-qa.json').read_text())
+target = baseline['target']
+assert target['database'].endswith('_test') and int(target['port']) == 55441
+BASE = 'http://127.0.0.1:18097'
+EXPECTED = f"{target['database']}:55441"
+PHP = 'C:/Users/macbook/.config/investmoz/php-8.5.11/php.exe'
+version = subprocess.check_output([PHP, '-r', "echo hash_file('xxh128', 'public/build-qa-opportunities/manifest.json');"], cwd=ROOT, text=True).strip()
+events = []
+receipt_path = PRIVATE / 'profiles-v1-http-receipts-qa.json'
+receipts = json.loads(receipt_path.read_text()) if receipt_path.exists() else {}
+REASON = 'Ensaio sintético QA de perfis, representação e segregação de funções'
+
+
+def save():
+ receipt_path.write_text(json.dumps(receipts, indent=2), encoding='utf-8')
+
+
+def otp(secret):
+ digest = hmac.new(base64.b32decode(secret), struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ return f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+
+
+class QAOnlyRedirect(urllib.request.HTTPRedirectHandler):
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ assert newurl.startswith(BASE + '/'), 'Non-QA redirect refused'
+ return super().redirect_request(req, fp, code, msg, headers, newurl)
+
+
+class Session:
+ def __init__(self, role):
+ self.role = role
+ self.jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(QAOnlyRedirect(), urllib.request.HTTPCookieProcessor(self.jar))
+ self.checked = False
+
+ def call(self, method, path, data=None, status=200, inertia=False, binary=False, multipart=None):
+ assert path.startswith('/') and not path.startswith('//')
+ assert method == 'GET' or self.checked, 'Read-only QA probe required before writes'
+ headers = {'Accept': 'application/json'}
+ for cookie in self.jar:
+ if cookie.name == 'XSRF-TOKEN':
+ headers['X-XSRF-TOKEN'] = urllib.parse.unquote(cookie.value)
+ if inertia:
+ headers.update({'X-Inertia': 'true', 'X-Inertia-Version': version})
+ body = None
+ if multipart:
+ boundary = 'qa' + uuid.uuid4().hex
+ parts = []
+ for key, value in data.items():
+ parts.append(f'--{boundary}\r\nContent-Disposition: form-data; name="{key}"\r\n\r\n{value}\r\n'.encode())
+ parts.append(f'--{boundary}\r\nContent-Disposition: form-data; name="file"; filename="synthetic-qa-proof.txt"\r\nContent-Type: text/plain\r\n\r\n'.encode() + multipart + b'\r\n')
+ parts.append(f'--{boundary}--\r\n'.encode())
+ body = b''.join(parts)
+ headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary
+ elif data is not None:
+ body = json.dumps(data).encode()
+ headers['Content-Type'] = 'application/json'
+ request = urllib.request.Request(BASE + path, data=body, headers=headers, method=method)
+ try:
+ response = self.opener.open(request)
+ except urllib.error.HTTPError as error:
+ response = error
+ assert response.headers.get('X-Investmoz-QA-Target') == EXPECTED, 'Actual QA target mismatch'
+ self.checked = True
+ raw = response.read()
+ events.append({'actor_id': actors[self.role]['id'], 'method': method, 'path': path.split('?')[0], 'status': response.status})
+ if response.status != status:
+ diagnostic = {'actor_id': actors[self.role]['id'], 'method': method, 'path': path, 'expected': status, 'observed': response.status}
+ try:
+ diagnostic['error_fields'] = list(json.loads(raw).get('errors', {}))
+ except Exception:
+ pass
+ (PRIVATE / 'profiles-v1-last-failure-qa.json').write_text(json.dumps(diagnostic), encoding='utf-8')
+ raise AssertionError(f'{method} {path}: expected {status}, observed {response.status}; response body withheld')
+ if binary:
+ return raw
+ return json.loads(raw) if raw else None
+
+ def login(self):
+ self.call('GET', '/login', binary=True)
+ account = actors[self.role]
+ result = self.call('POST', '/login', {'email': account['email'], 'password': account['password']})
+ if result.get('two_factor'):
+ self.call('POST', '/two-factor-challenge', {'code': otp(account['totp_secret'])}, status=204)
+ return self
+
+ def enroll(self):
+ self.login()
+ if not actors[self.role].get('enrolled'):
+ self.call('POST', '/user/confirm-password', {'password': actors[self.role]['password']}, status=201)
+ if not actors[self.role].get('totp_secret'):
+ self.call('POST', '/user/two-factor-authentication')
+ actors[self.role]['totp_secret'] = self.call('GET', '/user/two-factor-secret-key')['secretKey']
+ ACTOR_FILE.write_text(json.dumps(actors, indent=2), encoding='utf-8')
+ self.call('POST', '/user/confirmed-two-factor-authentication', {'code': otp(actors[self.role]['totp_secret'])})
+ actors[self.role]['enrolled'] = True
+ ACTOR_FILE.write_text(json.dumps(actors, indent=2), encoding='utf-8')
+ self.call('POST', '/logout', {}, status=204)
+
+
+def promoter_request(role, organization):
+ if role in receipts.get('requests', {}):
+ return receipts['requests'][role]
+ s = Session(role).login()
+ case = s.call('POST', '/balcao-virtual/dossiers', {'title': 'Synthetic QA profile proof ' + role, 'client_key': str(uuid.uuid4()), 'reuse_consent': True}, status=201)
+ raw = ('Synthetic QA-only proof. Not a real identity or legal document. ' + role + ' ' + str(uuid.uuid4())).encode()
+ s.call('POST', f"/balcao-virtual/dossiers/{case['id']}/documentos", {'version': case['version'], 'category': 'profile-proof-qa', 'source_reference': 'Synthetic QA, not official, not for publication', 'consent': '1'}, multipart=raw)
+ details = s.call('GET', f"/balcao-virtual/dossiers/{case['id']}")
+ document = details['documents'][-1]
+ assert document['malware_scan_status'] == 'clean' and document['sha256'].strip() == hashlib.sha256(raw).hexdigest(), 'Real scan not completed'
+ payload = {'creation_key': str(uuid.uuid4()), 'representation_type': 'company' if organization else 'individual', 'organization_id': organization,
+ 'opportunity_types': ['investment_project'], 'document_ids': [document['document_id']], 'reason': REASON}
+ request = s.call('POST', '/perfil/promotor', payload, status=201)
+ replay = s.call('POST', '/perfil/promotor', payload, status=201)
+ assert replay['id'] == request['id']
+ new = Session(role).login()
+ recovered = new.call('GET', '/perfil/promotor/' + request['id'])
+ assert recovered['status'] == 'pending'
+ receipts.setdefault('requests', {})[role] = {'id': request['id'], 'document_id': document['document_id'], 'document_sha256': hashlib.sha256(raw).hexdigest(), 'case_id': case['id'], 'approved': False}
+ save()
+ return receipts['requests'][role]
+
+
+def grant(role, granted_role):
+ key = role + ':' + granted_role
+ if key not in receipts.get('grants', {}):
+ s = Session('super_first').login()
+ result = s.call('POST', '/perfis/atribuicoes', {'user_id': actors[role]['id'], 'role': granted_role, 'opportunity_types': ['investment_project'], 'reason': REASON, 'responsibilities': []}, status=201)
+ receipts.setdefault('grants', {})[key] = result['id']
+ save()
+
+
+if '--verify-current-only' in sys.argv:
+ draft = receipts['draft']['id']
+ promoter = Session('promoter').login()
+ nav = promoter.call('GET', '/dashboard', inertia=True)['props']['profileAccess']
+ assert nav['mine'] == '/minhas-oportunidades' and nav['create'] == '/minhas-oportunidades/create'
+ promoter.call('GET', nav['mine'], inertia=True)
+ promoter.call('GET', nav['create'], inertia=True)
+ promoter.call('GET', '/management/territory-options?type=province', status=403)
+ provinces = promoter.call('GET', '/minhas-oportunidades/territory-options?type=province')['data']
+ assert len(provinces) == 11
+ province = provinces[0]
+ geometry = promoter.call('GET', '/minhas-oportunidades/territory-geometries?territory_id=' + province['id'])
+ assert geometry['selected_geometry_available']
+ before = promoter.call('GET', f'/minhas-oportunidades/{draft}/edit', inertia=True)['props']
+ promoter.call('PUT', f'/minhas-oportunidades/{draft}/draft', {'etag': before['etag'], 'geography_scope': 'specific', 'province_id': province['id'], 'reason': REASON})
+ recovered = Session('promoter').login().call('GET', f'/minhas-oportunidades/{draft}/edit', inertia=True)['props']
+ assert recovered['territoryPath'][0]['id'] == province['id'] and recovered['territoryPath'][0]['name'] == province['name']
+ colleague = Session('colleague').login()
+ colleague.call('GET', f'/minhas-oportunidades/{draft}/edit', inertia=True)
+ colleague.call('GET', f'/minhas-oportunidades/{draft}/resources', inertia=True)
+ Session('outsider').login().call('GET', f'/minhas-oportunidades/{draft}/view', inertia=True, status=403)
+ public = Session('public').login()
+ public.call('GET', '/minhas-oportunidades/territory-options?type=province', status=403)
+ Session('validator').login().call('GET', '/minhas-oportunidades', inertia=True, status=403)
+ Session('publisher').login().call('GET', f'/minhas-oportunidades/{draft}/view', inertia=True)
+ auditor = Session('auditor').login()
+ auditor.call('GET', '/perfis/auditoria?action=superuser_replaced', inertia=True)
+ auditor.call('GET', '/perfis/auditoria?action=superuser_replaced&format=json')
+ report = auditor.call('GET', '/qa-auditoria/pedidos-abertos', binary=True).decode('utf-8')
+ projection = json.loads((PRIVATE / 'pedidos-abertos-projection.json').read_text(encoding='utf-8'))
+ assert report.count('make(Kernel::class)->bootstrap();
+$identity = portalQaAssertTarget($target);
+$directory = $root.'/storage/app/private/investmoz-v2/portal-audit';
+$private = $directory.'/profiles-v1-actors-private.json';
+$baselinePath = $directory.'/profiles-v1-before-qa.json';
+
+function snapshot(array $tables, ?array $baseline = null): array
+{
+ $result = [];
+ foreach ($tables as $table) {
+ $columns = $baseline[$table]['columns'] ?? Schema::getColumnListing($table);
+ $projection = implode(',', array_map(fn ($c) => '"'.$c.'"', $columns));
+ $identifier = in_array('id', $columns, true) ? 'id::text' : 'NULL::text';
+ $rows = DB::select('SELECT '.$identifier.' AS id, row_to_json(t)::text AS row FROM (SELECT '.$projection.' FROM "'.$table.'") t ORDER BY row_to_json(t)::text');
+ $result[$table] = ['columns' => $columns, 'rows' => []];
+ foreach ($rows as $row) {
+ $digest = hash('sha256', $row->row);
+ $result[$table]['rows'][$row->id ?? $digest] = $digest;
+ }
+ }
+ return $result;
+}
+
+$tables = ['users', 'opportunities', 'organizations', 'memberships', 'documents', 'opportunity_projects', 'opportunity_clusters', 'opportunity_images', 'opportunity_documents', 'opportunity_locations', 'geo_locations', 'geo_geometries', 'desk_cases', 'desk_requests', 'investment_dossiers', 'investor_journeys', 'journey_steps', 'audit_events'];
+$tables = array_values(array_filter($tables, fn ($t) => Schema::hasTable($t)));
+$mode = $argv[1] ?? 'inspect';
+if ($mode === 'prepare') {
+ if (! is_file($baselinePath)) {
+ file_put_contents($baselinePath, json_encode(['target' => $target, 'tables' => snapshot($tables), 'active_manifest_sha256' => hash_file('sha256', $root.'/public/build/manifest.json')], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+ }
+ if (! Schema::hasTable('portal_role_assignments')) {
+ config(['portal_profiles.authenticated_installation' => true]);
+ throw_unless(Artisan::call('migrate', ['--path' => 'database/migrations/2026_10_10_040000_create_portal_profile_authorization.php', '--force' => true]) === 0, RuntimeException::class, 'QA profile migration failed');
+ }
+ $actors = is_file($private) ? json_decode(file_get_contents($private), true, 512, JSON_THROW_ON_ERROR) : [];
+ foreach (['public', 'promoter', 'colleague', 'outsider', 'validator', 'publisher', 'auditor', 'super_first', 'super_second', 'bootstrap', 'replacement', 'multiple'] as $profile) {
+ if (isset($actors[$profile])) {
+ $user = User::findOrFail($actors[$profile]['id']);
+ throw_unless($user->email === $actors[$profile]['email'] && str_ends_with($user->email, '@example.invalid'), RuntimeException::class, 'Synthetic actor identity mismatch');
+ continue;
+ }
+ $email = 'profiles-v1-'.$profile.'@example.invalid';
+ throw_if(User::where('email', $email)->exists(), RuntimeException::class, 'Existing actor has no private QA receipt; do not rotate it implicitly');
+ $password = Str::password(40);
+ $user = User::create(['name' => 'QA profiles v1 '.$profile, 'email' => $email, 'password' => Hash::make($password)]);
+ $user->forceFill(['email_verified_at' => now()])->save();
+ $actors[$profile] = ['id' => $user->id, 'email' => $email, 'password' => $password];
+ file_put_contents($private, json_encode($actors, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+ }
+ foreach (['organization' => ['promoter', 'colleague', 'multiple'], 'other_organization' => ['outsider']] as $label => $members) {
+ $orgPath = $directory.'/profiles-v1-organizations-qa.json';
+ $organizations = is_file($orgPath) ? json_decode(file_get_contents($orgPath), true, 512, JSON_THROW_ON_ERROR) : [];
+ if (! isset($organizations[$label])) {
+ $organizations[$label] = (string) Str::uuid();
+ DB::table('organizations')->insert(['id' => $organizations[$label], 'source_system' => 'profiles-v1-qa', 'name' => 'Synthetic QA '.$label, 'organization_type' => 'private']);
+ file_put_contents($orgPath, json_encode($organizations, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+ }
+ foreach ($members as $member) {
+ if (! DB::table('memberships')->where('organization_id', $organizations[$label])->where('user_id', $actors[$member]['id'])->exists()) {
+ DB::table('memberships')->insert(['id' => (string) Str::uuid(), 'source_system' => 'profiles-v1-qa', 'organization_id' => $organizations[$label], 'user_id' => $actors[$member]['id'], 'role' => 'officer']);
+ }
+ }
+ }
+ echo json_encode(['target' => $identity, 'migration_installed_in_qa' => true, 'synthetic_actors' => array_map(fn ($a) => $a['id'], $actors), 'active_writes' => 0, 'mfa' => 'Enroll through authenticated Fortify; no direct MFA injection']).PHP_EOL;
+ exit;
+}
+if ($mode === 'verify') {
+ $baseline = json_decode(file_get_contents($baselinePath), true, 512, JSON_THROW_ON_ERROR);
+ $current = snapshot(array_keys($baseline['tables']), $baseline['tables']);
+ $preserved = [];
+ foreach ($baseline['tables'] as $table => $proof) {
+ $preserved[$table] = count(array_diff_assoc($proof['rows'], $current[$table]['rows'])) === 0;
+ }
+ $proof = ['target' => $identity, 'previous_rows_preserved_by_id_and_original_columns' => $preserved,
+ 'captured_at' => gmdate('c'), 'schema_installed' => Schema::hasTable('portal_role_assignments'),
+ 'fingerprints' => [
+ 'profiles' => hash('sha256', json_encode(array_map(fn ($path) => hash_file('sha256', $path), \App\Services\PortalProfileAccess::fingerprintFiles()), JSON_THROW_ON_ERROR)),
+ 'management' => app(\App\Services\OpportunityManagementInstallation::class)->fingerprint(),
+ 'resources' => app(\App\Services\OpportunityResourceInstallation::class)->fingerprint(),
+ 'desk_path' => app(\App\Services\VirtualDeskInstallation::class)->fingerprint(),
+ 'geometry' => app(\App\Services\TerritoryGeometryImport::class)->fingerprint(),
+ ],
+ 'active_manifest_preserved' => hash_file('sha256', $root.'/public/build/manifest.json') === $baseline['active_manifest_sha256'],
+ 'mfa18_unchanged' => $preserved['users'], 'pair' => Schema::hasTable('portal_superuser_pair') ? DB::table('portal_superuser_pair')->first() : null,
+ 'active_writes' => 0, 'browser_visual_observed' => false];
+ throw_unless(! in_array(false, $preserved, true) && $proof['active_manifest_preserved'], RuntimeException::class, 'Baseline preservation failed');
+ file_put_contents($directory.'/profiles-v1-preservation-qa.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+ echo json_encode($proof, JSON_THROW_ON_ERROR).PHP_EOL;
+ exit;
+}
+DB::beginTransaction();
+DB::statement('SET TRANSACTION READ ONLY');
+echo json_encode(['target' => $identity, 'schema_tables' => Schema::getTableListing(), 'opportunity_columns' => Schema::getColumnListing('opportunities'), 'active_writes' => 0], JSON_THROW_ON_ERROR).PHP_EOL;
+DB::rollBack();
diff --git a/tools/portal-resource-http-actors-qa.php b/tools/portal-resource-http-actors-qa.php
new file mode 100644
index 00000000..4d5f9a11
--- /dev/null
+++ b/tools/portal-resource-http-actors-qa.php
@@ -0,0 +1,69 @@
+make(Kernel::class)->bootstrap();
+portalQaAssertTarget($target);
+$private = $root.'/storage/app/private/investmoz-v2/portal-audit';
+$sessions = realpath($root.'/storage/app/private/investmoz-v2/qa-opportunity-resources-sessions');
+$privateRoot = realpath($root.'/storage/app/private/investmoz-v2');
+abort_unless($sessions && $privateRoot && str_starts_with($sessions, $privateRoot.DIRECTORY_SEPARATOR) && ! config('session.encrypt'), 422);
+abort_unless(($argv[1] ?? '') === '--rotate', 422, 'Explicit QA-only rotation required.');
+$actors = [];
+$before = [];
+foreach (['manager' => 'opportunity-manager@example.invalid', 'outsider' => 'investor-path-outsider-qa@example.invalid'] as $role => $email) {
+ $user = User::where('email', $email)->firstOrFail();
+ $before[$role] = $user->getRawOriginal();
+ $actors[$role] = ['id' => $user->id, 'email' => $email, 'password' => Str::password(40),
+ 'totp_secret' => $user->two_factor_secret ? Crypt::decryptString($user->two_factor_secret) : null];
+}
+$account18 = DB::table('users')->where('id', 18)->first();
+$account18Hash = hash('sha256', json_encode($account18, JSON_THROW_ON_ERROR));
+DB::transaction(function () use ($actors): void {
+ foreach ($actors as $actor) {
+ DB::table('users')->where('id', $actor['id'])->where('email', $actor['email'])
+ ->update(['password' => Hash::make($actor['password']), 'remember_token' => Str::random(60), 'updated_at' => now()]);
+ }
+});
+$invalidated = 0;
+foreach (glob($sessions.DIRECTORY_SEPARATOR.'*') ?: [] as $file) {
+ $path = realpath($file);
+ if (! $path || ! is_file($path) || ! str_starts_with($path, $sessions.DIRECTORY_SEPARATOR) || ! preg_match('/^[a-zA-Z0-9]{40}$/', basename($path))) {
+ continue;
+ }
+ $data = @unserialize(file_get_contents($path), ['allowed_classes' => false]);
+ if (! is_array($data)) {
+ continue;
+ }
+ foreach ($data as $key => $value) {
+ if ((str_starts_with($key, 'login_web_') || $key === 'login.id') && in_array((int) $value, array_column($actors, 'id'), true)) {
+ abort_unless(unlink($path), 422, 'QA session invalidation failed.');
+ $invalidated++;
+ break;
+ }
+ }
+}
+foreach ($actors as $role => $actor) {
+ $after = DB::table('users')->where('id', $actor['id'])->first();
+ foreach (['two_factor_secret', 'two_factor_recovery_codes', 'two_factor_confirmed_at'] as $column) {
+ abort_unless($before[$role][$column] === $after->$column, 422, 'MFA preservation check failed.');
+ }
+ abort_unless(! hash_equals($before[$role]['password'], $after->password), 422);
+}
+abort_unless($account18Hash === hash('sha256', json_encode(DB::table('users')->where('id', 18)->first(), JSON_THROW_ON_ERROR)), 422, 'Unrelated investor preservation check failed.');
+file_put_contents($private.'/resource-http-actors-private.json', json_encode($actors, JSON_THROW_ON_ERROR));
+$proof = ['captured_at' => gmdate('c'), 'target' => $target, 'rotated_synthetic_actors' => count($actors), 'qa_sessions_invalidated' => $invalidated,
+ 'remember_tokens_rotated' => true, 'mfa_preserved' => true, 'investor_18_preserved' => true, 'active_writes' => 0, 'credentials_exported' => false];
+file_put_contents($private.'/resource-http-actors-rotation-qa.json', json_encode($proof, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
+echo json_encode($proof, JSON_THROW_ON_ERROR).PHP_EOL;
diff --git a/tools/portal-resources-real-http-qa.py b/tools/portal-resources-real-http-qa.py
index f7df60d4..03bd54f5 100644
--- a/tools/portal-resources-real-http-qa.py
+++ b/tools/portal-resources-real-http-qa.py
@@ -1,8 +1,12 @@
"""Real upload/scans/derivatives/download through the QA web PHP process; no visual claim."""
+import base64
import hashlib
+import hmac
+import time
import http.cookiejar
import json
import re
+import sys
import struct
import subprocess
import urllib.error
@@ -22,7 +26,8 @@ expected = target['database'] + ':55441'
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
events = []
-asset_version = subprocess.check_output(['php', '-r', "echo hash_file('xxh128','public/build/manifest.json');"], cwd=root, text=True).strip()
+php = Path.home() / '.config/investmoz/php-8.5.11/php.exe'
+asset_version = subprocess.check_output([str(php), '-r', "echo hash_file('xxh128','public/build-qa-opportunities/manifest.json');"], cwd=root, text=True).strip()
def call(method, path, data=None, status=200, binary=False, upload=None, inertia=False, html=False):
@@ -56,12 +61,67 @@ def call(method, path, data=None, status=200, binary=False, upload=None, inertia
return (raw, response.headers) if binary else None if html or not raw else json.loads(raw)
+actors = json.loads((private / 'resource-http-actors-private.json').read_text(encoding='utf-8-sig'))
+
+
+def login(role):
+ credentials = actors[role]
+ result = call('POST', '/login', {k: credentials[k] for k in ['email', 'password']})
+ if result.get('two_factor'):
+ secret = base64.b32decode(credentials['totp_secret'])
+ digest = hmac.new(secret, struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ code = f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+ call('POST', '/two-factor-challenge', {'code': code}, status=204)
+
+
call('GET', '/login', html=True)
-call('POST', '/login', {'email': 'opportunity-manager@example.invalid', 'password': 'Opportunity-QA-2026!'})
+login('manager')
installation = call('GET', '/management/opportunity-resources-install')
assert installation['installed'] and installation['imageProcessingAvailable']
-draft = call('POST', '/management/opportunities/drafts', {'creation_key': str(uuid.uuid4()), 'reason': 'Ensaio de operações documentais web com ClamD real em QA'}, status=201)
-id = draft['id']
+if '--verify-only' in sys.argv:
+ retained = json.loads((private / 'resources-real-http-qa.json').read_text(encoding='utf-8-sig'))
+ assert retained['target'] == target and retained['valid_pdf_only_increment'] and retained['original_pdf_strictly_parseable']
+ base = f"/management/opportunities/{retained['opportunity_id']}/resources"
+ resource_props = call('GET', base, inertia=True)['props']
+ previous = next(json.loads(p.read_text(encoding='utf-8-sig')) for p in private.glob('resources-real-http-qa-*.json')
+ if json.loads(p.read_text(encoding='utf-8-sig'))['document_resource_id'] == retained['previous_document_resource_id'])
+ old_pdf, _ = call('GET', base + '/documents/' + previous['document_resource_id'] + '/download', binary=True)
+ old_pdf_sha = previous.get('original_pdf_sha256', hashlib.sha256(b'%PDF-1.7\nSynthetic web QA only\n%%EOF').hexdigest())
+ assert hashlib.sha256(old_pdf).hexdigest() == old_pdf_sha
+ old_image, _ = call('GET', base + '/images/' + previous['image_resource_id'] + '/download', binary=True)
+ assert hashlib.sha256(old_image).hexdigest() == previous['original_image_sha256']
+ image_record = next(r for r in resource_props['resources']['images'] if r['id'] == previous['image_resource_id'])
+ old_derived = {d['document_id']: d['sha256'] for d in previous['derivatives']}
+ for derivative in image_record['derivativePreviews']:
+ url = urllib.parse.urlsplit(derivative['url'])
+ assert url.hostname == '127.0.0.1' and url.port == 18097
+ content, _ = call('GET', url.path + '?' + url.query, binary=True)
+ assert hashlib.sha256(content).hexdigest() == old_derived[derivative['document_id']]
+ new_pdf, _ = call('GET', base + '/documents/' + retained['document_resource_id'] + '/download', binary=True)
+ assert hashlib.sha256(new_pdf).hexdigest() == retained['original_pdf_sha256']
+ sys.path.insert(0, str(private / 'pdf-proof-tooling'))
+ import io
+ import pypdf
+ reader = pypdf.PdfReader(io.BytesIO(new_pdf), strict=True)
+ assert len(reader.pages) == 1 and 'no official or legal value' in reader.pages[0].extract_text()
+ call('POST', '/logout', status=204)
+ proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'previous_binaries_preserved': 5,
+ 'new_valid_pdf_resource_id': retained['document_resource_id'], 'new_valid_pdf_sha256': retained['original_pdf_sha256'],
+ 'new_pdf_pages': 1, 'new_pdf_strict_parse': True, 'resources_created': 0, 'published': False,
+ 'requests': events, 'interface_observed': False, 'active_writes': 0}
+ (private / 'resource-originals-preservation-http-qa.json').write_text(json.dumps(proof, indent=2), encoding='utf-8')
+ print(json.dumps({k: v for k, v in proof.items() if k not in ['requests', 'new_valid_pdf_resource_id', 'new_valid_pdf_sha256']}))
+ sys.exit(0)
+
+valid_pdf_only = '--valid-pdf-only' in sys.argv
+retained = json.loads((private / 'resources-real-http-qa.json').read_text(encoding='utf-8-sig')) if valid_pdf_only else None
+if retained:
+ assert retained['target'] == target and not retained['published']
+ id = retained['opportunity_id']
+else:
+ draft = call('POST', '/management/opportunities/drafts', {'creation_key': str(uuid.uuid4()), 'reason': 'Ensaio de operações documentais web com ClamD real em QA'}, status=201)
+ id = draft['id']
base = f'/management/opportunities/{id}/resources'
@@ -73,14 +133,19 @@ def input(payload):
return {'etag': props()['etag'], 'creation_key': str(uuid.uuid4()), 'payload': payload, 'reason': 'Ensaio real de gravação e recuperação de recursos privados QA'}
-document_bytes = b'%PDF-1.7\nSynthetic web QA only\n%%EOF'
-document = call('POST', base + '/documents', input({'title': 'Synthetic web QA document'}), upload=('qa.pdf', 'application/pdf', document_bytes), status=201)
+pdf_proof = json.loads((private / 'document-types-fixture-qa.json').read_text(encoding='utf-8-sig'))
+document_bytes = (private / 'synthetic-valid-original.pdf').read_bytes()
+assert hashlib.sha256(document_bytes).hexdigest() == pdf_proof['fixtures'][0]['sha256'] and pdf_proof['fixtures'][0]['strict_parse']
+document = call('POST', base + '/documents', input({'title': 'Synthetic QA PDF - valid one page, no legal value'}), upload=('qa-valid-one-page.pdf', 'application/pdf', document_bytes), status=201)
+document_record = next(r for r in props()['resources']['documents'] if r['id'] == document['id'])
+assert document_record['file']['malware_scan_status'] == 'clean' and document_record['file']['malware_engine'] == 'ClamAV'
chunk = lambda name, content: struct.pack('>I', len(content)) + name + content + struct.pack('>I', zlib.crc32(name + content))
png = b'\x89PNG\r\n\x1a\n' + chunk(b'IHDR', struct.pack('>IIBBBBB', 1600, 1600, 8, 2, 0, 0, 0)) + chunk(b'IDAT', zlib.compress(bytes(1600 * 4801))) + chunk(b'IEND', b'')
-image = call('POST', base + '/images', input({'title': 'Synthetic web QA image', 'caption': 'Synthetic square no active data', 'alt_text': 'Synthetic square for QA only', 'rights_status': 'owned'}), upload=('qa.png', 'image/png', png), status=201)
+image = {'id': retained['image_resource_id']} if retained else call('POST', base + '/images', input({'title': 'Synthetic web QA image', 'caption': 'Synthetic square no active data', 'alt_text': 'Synthetic square for QA only', 'rights_status': 'owned'}), upload=('qa.png', 'image/png', png), status=201)
original = next(r for r in props()['resources']['images'] if r['id'] == image['id'])
assert original['file']['malware_scan_status'] == 'clean' and original['file']['malware_engine'] == 'ClamAV'
-call('POST', base + '/images/' + image['id'] + '/prepare', {'etag': props()['etag'], 'version': original['version'], 'reason': 'Preparar três derivadas na execução PHP web QA'})
+if not valid_pdf_only:
+ call('POST', base + '/images/' + image['id'] + '/prepare', {'etag': props()['etag'], 'version': original['version'], 'reason': 'Preparar três derivadas na execução PHP web QA'})
p = props()
prepared = next(r for r in p['resources']['images'] if r['id'] == image['id'])
assert len(prepared['derivativePreviews']) == 3
@@ -99,19 +164,23 @@ for kind, resource, expected_bytes in [('documents', document, document_bytes),
call('POST', '/logout', status=204)
jar.clear()
call('GET', '/login', html=True)
-call('POST', '/login', {'email': 'investor-path-outsider-qa@example.invalid', 'password': 'Outsider-Path-QA-2026!'})
+login('outsider')
call('GET', base + '/documents/' + document['id'] + '/download', status=403)
call('GET', url.path + '?' + url.query, status=403)
call('POST', '/logout', status=204)
jar.clear()
call('GET', '/login', html=True)
-call('POST', '/login', {'email': 'opportunity-manager@example.invalid', 'password': 'Opportunity-QA-2026!'})
+login('manager')
recovered = next(r for r in props()['resources']['images'] if r['id'] == image['id'])
assert len(recovered['derivativePreviews']) == 3 and recovered['document_id'] == original['document_id']
recovered_bytes, _ = call('GET', base + '/documents/' + document['id'] + '/download', binary=True)
assert recovered_bytes == document_bytes
-proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'code_hash': installation['code_hash'], 'asset_version': asset_version, 'opportunity_id': id, 'document_resource_id': document['id'], 'image_resource_id': image['id'], 'original_image_document_id': original['document_id'], 'original_image_sha256': hashlib.sha256(png).hexdigest(), 'web_gd_available': True, 'original_image_engine': original['file']['malware_engine'], 'derivatives': derivatives, 'requests': events, 'new_authenticated_session_recovered': True, 'api_persistence_passed': True, 'interface_observed': False, 'published': False, 'active_writes': 0}
+call('POST', '/logout', status=204)
+proof = {'captured_at': datetime.now(timezone.utc).isoformat(), 'target': target, 'code_hash': installation['code_hash'], 'asset_version': asset_version, 'opportunity_id': id, 'document_resource_id': document['id'], 'original_pdf_sha256': hashlib.sha256(document_bytes).hexdigest(), 'original_pdf_strictly_parseable': True, 'pdf_fixture_evidence': 'document-types-fixture-qa.json', 'image_resource_id': image['id'], 'original_image_document_id': original['document_id'], 'original_image_sha256': hashlib.sha256(png).hexdigest(), 'web_gd_available': True, 'original_image_engine': original['file']['malware_engine'], 'derivatives': derivatives, 'requests': events, 'new_authenticated_session_recovered': True, 'api_persistence_passed': True, 'interface_observed': False, 'published': False, 'active_writes': 0}
destination = private / 'resources-real-http-qa.json'
+proof.update({'valid_pdf_only_increment': valid_pdf_only, 'new_derivative_scans_performed': not valid_pdf_only,
+ 'existing_originals_replaced': False, 'original_pdf_real_scan_engine': document_record['file']['malware_engine'],
+ 'previous_document_resource_id': retained['document_resource_id'] if retained else None})
if destination.exists():
destination.rename(private / ('resources-real-http-qa-' + datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') + '.json'))
destination.write_text(json.dumps(proof, indent=2), encoding='utf-8')
diff --git a/tools/portal_profiles_http_session.py b/tools/portal_profiles_http_session.py
new file mode 100644
index 00000000..20924f5c
--- /dev/null
+++ b/tools/portal_profiles_http_session.py
@@ -0,0 +1,157 @@
+"""Profile acceptance through the guarded QA server. No credential/OTP/header output."""
+import base64
+import hashlib
+import hmac
+import http.cookiejar
+import json
+import struct
+import subprocess
+import sys
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+import uuid
+from datetime import datetime, timezone
+from pathlib import Path
+
+ROOT = Path(__file__).resolve().parent.parent
+PRIVATE = ROOT / 'storage/app/private/investmoz-v2/portal-audit'
+ACTOR_FILE = PRIVATE / 'profiles-v1-actors-private.json'
+actors = json.loads(ACTOR_FILE.read_text(encoding='utf-8-sig'))
+organizations = json.loads((PRIVATE / 'profiles-v1-organizations-qa.json').read_text())
+baseline = json.loads((PRIVATE / 'profiles-v1-before-qa.json').read_text())
+target = baseline['target']
+assert target['database'].endswith('_test') and int(target['port']) == 55441
+BASE = 'http://127.0.0.1:18097'
+EXPECTED = f"{target['database']}:55441"
+PHP = 'C:/Users/macbook/.config/investmoz/php-8.5.11/php.exe'
+version = subprocess.check_output([PHP, '-r', "echo hash_file('xxh128', 'public/build-qa-opportunities/manifest.json');"], cwd=ROOT, text=True).strip()
+events = []
+receipt_path = PRIVATE / 'profiles-v1-http-receipts-qa.json'
+receipts = json.loads(receipt_path.read_text()) if receipt_path.exists() else {}
+REASON = 'Ensaio sintético QA de perfis, representação e segregação de funções'
+
+
+def save():
+ receipt_path.write_text(json.dumps(receipts, indent=2), encoding='utf-8')
+
+
+def otp(secret):
+ digest = hmac.new(base64.b32decode(secret), struct.pack('>Q', int(time.time()) // 30), hashlib.sha1).digest()
+ offset = digest[-1] & 15
+ return f'{(struct.unpack(">I", digest[offset:offset + 4])[0] & 0x7fffffff) % 1000000:06d}'
+
+
+class QAOnlyRedirect(urllib.request.HTTPRedirectHandler):
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ assert newurl.startswith(BASE + '/'), 'Non-QA redirect refused'
+ return super().redirect_request(req, fp, code, msg, headers, newurl)
+
+
+class Session:
+ def __init__(self, role):
+ self.role = role
+ self.jar = http.cookiejar.CookieJar()
+ self.opener = urllib.request.build_opener(QAOnlyRedirect(), urllib.request.HTTPCookieProcessor(self.jar))
+ self.checked = False
+
+ def call(self, method, path, data=None, status=200, inertia=False, binary=False, multipart=None):
+ assert path.startswith('/') and not path.startswith('//')
+ assert method == 'GET' or self.checked, 'Read-only QA probe required before writes'
+ headers = {'Accept': 'application/json'}
+ for cookie in self.jar:
+ if cookie.name == 'XSRF-TOKEN':
+ headers['X-XSRF-TOKEN'] = urllib.parse.unquote(cookie.value)
+ if inertia:
+ headers.update({'X-Inertia': 'true', 'X-Inertia-Version': version})
+ body = None
+ if multipart:
+ boundary = 'qa' + uuid.uuid4().hex
+ parts = []
+ for key, value in data.items():
+ parts.append(f'--{boundary}\r\nContent-Disposition: form-data; name="{key}"\r\n\r\n{value}\r\n'.encode())
+ filename, mime, file_bytes = multipart if isinstance(multipart, tuple) else ('synthetic-qa-proof.txt', 'text/plain', multipart)
+ assert '\r' not in filename and '\n' not in filename and '"' not in filename
+ parts.append(f'--{boundary}\r\nContent-Disposition: form-data; name="file"; filename="{filename}"\r\nContent-Type: {mime}\r\n\r\n'.encode() + file_bytes + b'\r\n')
+ parts.append(f'--{boundary}--\r\n'.encode())
+ body = b''.join(parts)
+ headers['Content-Type'] = 'multipart/form-data; boundary=' + boundary
+ elif data is not None:
+ body = json.dumps(data).encode()
+ headers['Content-Type'] = 'application/json'
+ request = urllib.request.Request(BASE + path, data=body, headers=headers, method=method)
+ try:
+ response = self.opener.open(request)
+ except urllib.error.HTTPError as error:
+ response = error
+ assert response.headers.get('X-Investmoz-QA-Target') == EXPECTED, 'Actual QA target mismatch'
+ self.checked = True
+ raw = response.read()
+ events.append({'actor_id': actors[self.role]['id'], 'method': method, 'path': path.split('?')[0], 'status': response.status})
+ if response.status != status:
+ diagnostic = {'actor_id': actors[self.role]['id'], 'method': method, 'path': path, 'expected': status, 'observed': response.status}
+ try:
+ diagnostic['error_fields'] = list(json.loads(raw).get('errors', {}))
+ except Exception:
+ pass
+ (PRIVATE / 'profiles-v1-last-failure-qa.json').write_text(json.dumps(diagnostic), encoding='utf-8')
+ raise AssertionError(f'{method} {path}: expected {status}, observed {response.status}; response body withheld')
+ if binary:
+ return raw
+ return json.loads(raw) if raw else None
+
+ def login(self):
+ self.call('GET', '/login', binary=True)
+ account = actors[self.role]
+ result = self.call('POST', '/login', {'email': account['email'], 'password': account['password']})
+ if result.get('two_factor'):
+ self.call('POST', '/two-factor-challenge', {'code': otp(account['totp_secret'])}, status=204)
+ return self
+
+ def enroll(self):
+ self.login()
+ if not actors[self.role].get('enrolled'):
+ self.call('POST', '/user/confirm-password', {'password': actors[self.role]['password']}, status=201)
+ if not actors[self.role].get('totp_secret'):
+ self.call('POST', '/user/two-factor-authentication')
+ actors[self.role]['totp_secret'] = self.call('GET', '/user/two-factor-secret-key')['secretKey']
+ ACTOR_FILE.write_text(json.dumps(actors, indent=2), encoding='utf-8')
+ self.call('POST', '/user/confirmed-two-factor-authentication', {'code': otp(actors[self.role]['totp_secret'])})
+ actors[self.role]['enrolled'] = True
+ ACTOR_FILE.write_text(json.dumps(actors, indent=2), encoding='utf-8')
+ self.call('POST', '/logout', {}, status=204)
+
+
+def promoter_request(role, organization):
+ if role in receipts.get('requests', {}):
+ return receipts['requests'][role]
+ s = Session(role).login()
+ case = s.call('POST', '/balcao-virtual/dossiers', {'title': 'Synthetic QA profile proof ' + role, 'client_key': str(uuid.uuid4()), 'reuse_consent': True}, status=201)
+ raw = ('Synthetic QA-only proof. Not a real identity or legal document. ' + role + ' ' + str(uuid.uuid4())).encode()
+ s.call('POST', f"/balcao-virtual/dossiers/{case['id']}/documentos", {'version': case['version'], 'category': 'profile-proof-qa', 'source_reference': 'Synthetic QA, not official, not for publication', 'consent': '1'}, multipart=raw)
+ details = s.call('GET', f"/balcao-virtual/dossiers/{case['id']}")
+ document = details['documents'][-1]
+ assert document['malware_scan_status'] == 'clean' and document['sha256'].strip() == hashlib.sha256(raw).hexdigest(), 'Real scan not completed'
+ payload = {'creation_key': str(uuid.uuid4()), 'representation_type': 'company' if organization else 'individual', 'organization_id': organization,
+ 'opportunity_types': ['investment_project'], 'document_ids': [document['document_id']], 'reason': REASON}
+ request = s.call('POST', '/perfil/promotor', payload, status=201)
+ replay = s.call('POST', '/perfil/promotor', payload, status=201)
+ assert replay['id'] == request['id']
+ new = Session(role).login()
+ recovered = new.call('GET', '/perfil/promotor/' + request['id'])
+ assert recovered['status'] == 'pending'
+ receipts.setdefault('requests', {})[role] = {'id': request['id'], 'document_id': document['document_id'], 'document_sha256': hashlib.sha256(raw).hexdigest(), 'case_id': case['id'], 'approved': False}
+ save()
+ return receipts['requests'][role]
+
+
+def grant(role, granted_role):
+ key = role + ':' + granted_role
+ if key not in receipts.get('grants', {}):
+ s = Session('super_first').login()
+ result = s.call('POST', '/perfis/atribuicoes', {'user_id': actors[role]['id'], 'role': granted_role, 'opportunity_types': ['investment_project'], 'reason': REASON, 'responsibilities': []}, status=201)
+ receipts.setdefault('grants', {})[key] = result['id']
+ save()
+
+
diff --git a/vite.config.ts b/vite.config.ts
index d3011741..bfd0b4c4 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -7,9 +7,12 @@ import laravel from 'laravel-vite-plugin';
import { bunny } from 'laravel-vite-plugin/fonts';
import { defineConfig, lazyPlugins } from 'vite-plus';
+const qaBuild = process.env.INVESTMOZ_QA_BUILD === '1';
+
export default defineConfig({
plugins: lazyPlugins(() => [
laravel({
+ buildDirectory: qaBuild ? 'build-qa-opportunities' : 'build',
input: ['resources/css/app.css', 'resources/js/app.tsx'],
refresh: true,
fonts: [
@@ -24,9 +27,8 @@ export default defineConfig({
presets: [reactCompilerPreset()],
}),
tailwindcss(),
- wayfinder({
- formVariants: true,
- }),
+ // Reuse generated URLs in QA without booting the active Laravel environment.
+ ...(!qaBuild ? [wayfinder({ formVariants: true })] : []),
]),
server: {
// Laravel's public/hot points to IPv4 loopback; bind Vite there explicitly.