setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); (new ReflectionProperty(Database::class, 'instance'))->setValue(null, $pdo); $pdo->exec('CREATE TABLE auth_identities (id INTEGER PRIMARY KEY, status TEXT)'); $pdo->exec('CREATE TABLE students (id INTEGER PRIMARY KEY, grade_level TEXT, identity_id INTEGER)'); $pdo->exec("INSERT INTO auth_identities VALUES (1, 'active'), (2, 'disabled')"); $pdo->exec("INSERT INTO students VALUES (7, 'grade_10', 1), (8, 'grade_9', 1), (10, 'grade_10', 2)"); function checkContent(bool $condition, string $message): void { if (!$condition) throw new RuntimeException($message); } $asset = ['grade_key' => 'grade_10', 'storage_driver' => 'local', 'storage_key' => 'manifest.json']; checkContent(PublishedContentService::studentMayRead(7, $asset), 'Same-grade student denied'); checkContent(!PublishedContentService::studentMayRead(8, $asset), 'Other-grade student allowed'); checkContent(!PublishedContentService::studentMayRead(9, $asset), 'Unknown student allowed'); checkContent(!PublishedContentService::studentMayRead(10, $asset), 'Disabled identity allowed'); checkContent(PublishedContentService::readLocalAsset($asset) !== null, 'Exact in-root asset not found'); checkContent(PublishedContentService::readLocalAsset(array_merge($asset, ['storage_key' => '../../database_schema.sql'])) === null, 'Traversal escaped storage root'); checkContent(PublishedContentService::readLocalAsset(array_merge($asset, ['storage_key' => 'missing.md'])) === null, 'Missing file substituted'); checkContent(CurriculumService::getLessonMarkdown('../manifest.json') === '', 'Unsafe lesson read returned content'); checkContent(!CurriculumService::safeMarkdownPath('../grade_10/a.md'), 'Traversal path accepted'); checkContent(CurriculumService::safeMarkdownPath('grade_10/math_10/semester_1/unit_01/lesson_01.md'), 'Valid markdown path rejected'); echo "PASS 10 local content-access checks (not an HTTP/tenant test)\n";