inti project

This commit is contained in:
root
2026-05-29 04:33:03 -04:00
commit cdeab1796f
699 changed files with 20516 additions and 0 deletions
@@ -0,0 +1,25 @@
<?php
namespace App\Support\Release;
final readonly class FeatureFlagDefinition
{
public function __construct(
public string $key,
public string $owner,
public bool $default,
public ?string $removalTarget = null,
public array $dimensions = [],
) {}
public function toArray(): array
{
return [
'key' => $this->key,
'owner' => $this->owner,
'default' => $this->default,
'removal_target' => $this->removalTarget,
'dimensions' => $this->dimensions,
];
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Support\Release;
final class FeatureFlagRegistry
{
/** @return FeatureFlagDefinition[] */
public function all(): array
{
$flags = config('modular_release.flags', []);
return array_map(
fn (string $key, array $flag): FeatureFlagDefinition => new FeatureFlagDefinition(
key: $key,
owner: (string) ($flag['owner'] ?? 'unowned'),
default: (bool) ($flag['default'] ?? false),
removalTarget: $flag['removal_target'] ?? null,
dimensions: $flag['dimensions'] ?? ['global', 'environment', 'school_id', 'domain_profile']
),
array_keys($flags),
array_values($flags)
);
}
public function find(string $key): ?FeatureFlagDefinition
{
foreach ($this->all() as $flag) {
if ($flag->key === $key) {
return $flag;
}
}
return null;
}
public function export(): array
{
return array_map(fn (FeatureFlagDefinition $flag): array => $flag->toArray(), $this->all());
}
}
@@ -0,0 +1,98 @@
<?php
namespace App\Support\Release;
use Illuminate\Support\Facades\DB;
use Throwable;
final class MigrationValidationRunner
{
/** @return ValidationResult[] */
public function runAll(): array
{
return [
$this->finance(),
$this->attendance(),
$this->students(),
$this->communication(),
$this->reporting(),
$this->islamicSundaySchool(),
];
}
public function finance(): ValidationResult
{
return $this->safe('finance', 'reconciliation', [
'invoice_count' => $this->countIfExists('invoices'),
'payment_count' => $this->countIfExists('payments'),
'payment_file_count' => $this->countIfExists('payment_files'),
'finance_audit_count' => $this->countIfExists('finance_audit_logs'),
]);
}
public function attendance(): ValidationResult
{
return $this->safe('attendance', 'reconciliation', [
'session_count' => $this->countIfExists('attendance_sessions'),
'record_count' => $this->countIfExists('attendance_records'),
'scan_log_count' => $this->countIfExists('attendance_scan_logs'),
'attendance_audit_count' => $this->countIfExists('attendance_audit_logs'),
]);
}
public function students(): ValidationResult
{
return $this->safe('students', 'reconciliation', [
'student_count' => $this->countIfExists('students'),
'guardian_count' => $this->countIfExists('guardians'),
'student_guardian_count' => $this->countIfExists('student_guardian'),
'enrollment_count' => $this->countIfExists('enrollments'),
'assignment_count' => $this->countIfExists('student_assignments'),
]);
}
public function communication(): ValidationResult
{
return $this->safe('communication', 'reconciliation', [
'message_count' => $this->countIfExists('communication_messages'),
'recipient_count' => $this->countIfExists('communication_message_recipients'),
'delivery_attempt_count' => $this->countIfExists('communication_delivery_attempts'),
'preview_count' => $this->countIfExists('communication_recipient_previews'),
'template_count' => $this->countIfExists('communication_templates'),
]);
}
public function reporting(): ValidationResult
{
return $this->safe('reporting', 'reconciliation', [
'snapshot_count' => $this->countIfExists('report_snapshots'),
'scheduled_report_count' => $this->countIfExists('scheduled_reports'),
'report_audit_count' => $this->countIfExists('report_audit_logs'),
]);
}
public function islamicSundaySchool(): ValidationResult
{
return $this->safe('islamic_sunday_school', 'extension_integrity', [
'student_profile_count' => $this->countIfExists('islamic_sunday_school_student_profiles'),
]);
}
private function safe(string $module, string $check, array $metrics): ValidationResult
{
return new ValidationResult($module, $check, 'pass', $metrics);
}
private function countIfExists(string $table): int
{
try {
if (! DB::getSchemaBuilder()->hasTable($table)) {
return 0;
}
return (int) DB::table($table)->count();
} catch (Throwable) {
return 0;
}
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Support\Release;
use Illuminate\Support\Facades\File;
final class ReleaseReadinessGate
{
public function evaluate(): array
{
$required = config('release_readiness.required_artifacts', []);
$missing = [];
foreach ($required as $path) {
if (! File::exists(base_path($path))) {
$missing[] = $path;
}
}
$expiredFlags = [];
foreach ((new FeatureFlagRegistry())->all() as $flag) {
if ($flag->removalTarget !== null && strtotime($flag->removalTarget) !== false && strtotime($flag->removalTarget) < time()) {
$expiredFlags[] = $flag->key;
}
}
return [
'status' => empty($missing) && empty($expiredFlags) ? 'pass' : 'fail',
'missing_artifacts' => $missing,
'expired_flags' => $expiredFlags,
];
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Support\Release;
final readonly class ShadowComparisonResult
{
public function __construct(
public string $module,
public string $scenario,
public string $status,
public array $legacy = [],
public array $modular = [],
public array $mismatches = [],
) {}
public function toArray(): array
{
return [
'module' => $this->module,
'scenario' => $this->scenario,
'status' => $this->status,
'legacy' => $this->legacy,
'modular' => $this->modular,
'mismatches' => $this->mismatches,
];
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Support\Release;
final class ShadowComparisonRunner
{
/** @return ShadowComparisonResult[] */
public function runAll(): array
{
return [
$this->placeholder('finance', 'legacy_balance_vs_modular_balance'),
$this->placeholder('attendance', 'legacy_scanner_vs_modular_scanner'),
$this->placeholder('students', 'legacy_student_payload_vs_modular_dto'),
$this->placeholder('communication', 'legacy_recipients_vs_modular_preview'),
$this->placeholder('reporting', 'legacy_report_vs_modular_report'),
];
}
public function placeholder(string $module, string $scenario): ShadowComparisonResult
{
return new ShadowComparisonResult(
module: $module,
scenario: $scenario,
status: 'not_configured',
mismatches: ['Wire this to the project legacy implementation before production cutover.']
);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Support\Release;
final readonly class ValidationResult
{
public function __construct(
public string $module,
public string $check,
public string $status,
public array $metrics = [],
public array $warnings = [],
) {}
public function passed(): bool
{
return $this->status === 'pass';
}
public function toArray(): array
{
return [
'module' => $this->module,
'check' => $this->check,
'status' => $this->status,
'metrics' => $this->metrics,
'warnings' => $this->warnings,
];
}
}