# Phase 2 Execution Plan: Core Contracts and Module Boundaries


# Islamic Sunday School Alignment Update

Phase 2 must define contracts that support **Islamic Sunday School** through extension implementations, not by adding Islamic-specific language to the core interfaces.

Preferred extension namespace:

```text
App\Domain\IslamicSundaySchool
```

The core contracts remain school-neutral. Islamic Sunday School implementations may bind policies for:

```text
Qur'an progression
Arabic level placement
Islamic studies tracks
halaqa/class grouping
masjid family/community profile
program-session attendance
volunteer team communication
tuition, sadaqah, scholarship, and fee classification
```

Do not put these terms in `SchoolCore` contracts. The contracts define capabilities. The extension defines Islamic Sunday School behavior.

---
## Purpose

Phase 2 establishes the contract layer for the modular school platform. The goal is to define stable interfaces for shared school operations before moving implementation logic into `SchoolCore`.

This phase prevents the platform from becoming Sunday-School-shaped by accident. Islamic Sunday School may extend the global platform, but the global platform must not know Islamic Sunday School exists.

## Phase 2 Outcome

At the end of this phase:

- `SchoolCore` exposes stable contracts for core school operations.
- Islamic Sunday School behavior plugs into the platform through policies, providers, and extension services.
- Controllers and application services begin depending on contracts instead of concrete legacy services.
- Dependency direction is enforced by automated tests.
- No `SchoolCore` class imports from `IslamicSundaySchool`.
- New implementation work has a clear place to go instead of continuing the existing service sprawl.

## Dependency Rule

The dependency direction must be enforced as architecture law:

```text
Http / Controllers / Requests / Resources
        ↓
Application Services / Use Cases
        ↓
SchoolCore Contracts
        ↓
SchoolCore Implementations
        ↑
Domain Extensions, such as IslamicSundaySchool, may provide policies/providers
```

Allowed:

```text
IslamicSundaySchool → SchoolCore
Controllers → SchoolCore Contracts
Application Services → SchoolCore Contracts
SchoolCore Implementations → SchoolCore Models / Repositories
```

Forbidden:

```text
SchoolCore → IslamicSundaySchool
SchoolCore → Http Request
SchoolCore → auth()
SchoolCore → controller classes
SchoolCore → route-specific assumptions
SchoolCore → Islamic Sunday School program calendar assumptions
SchoolCore → masjid/community/ministry vocabulary unless stored as extension metadata
```

## Required Namespace Structure

Create this structure first. Do not migrate every class immediately. Empty boundaries are acceptable at the start. Fake modularity is not.

```text
app/
  Domain/
    SchoolCore/
      Contracts/
      Context/
      Identity/
      Students/
      Guardians/
      Enrollment/
      Attendance/
      Academics/
      Finance/
      Communication/
      Files/
      Reporting/
      Authorization/
      Support/
    IslamicSundaySchool/
      Contracts/
      Providers/
      Policies/
      Attendance/
      Curriculum/
      Ministry/
      Families/
      Reports/
    Shared/
      Contracts/
      ValueObjects/
      Exceptions/
      Support/
  Providers/
    SchoolCoreServiceProvider.php
    IslamicSundaySchoolServiceProvider.php
```

## Contract Design Rules

Every contract must follow these rules:

1. Accept `SchoolContext` explicitly or be resolved from a context-aware application service.
2. Use DTOs/value objects for input where payloads are complex.
3. Return DTOs/read models where behavior crosses module boundaries.
4. Never accept raw `Request` objects.
5. Never call `auth()` inside domain services.
6. Never use Islamic Sunday School terminology in `SchoolCore` contracts.
7. Never expose Eloquent models as the required public contract unless the service is strictly internal.
8. Define authorization expectations explicitly.
9. Define transaction ownership explicitly for mutation methods.
10. Include failure behavior in the contract documentation.

## Core Contracts to Create

### Context

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface RequiresSchoolContext
{
    public function setSchoolContext(SchoolContext $context): void;
}
```

### Students

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Students\Data\CreateStudentData;
use App\Domain\SchoolCore\Students\Data\UpdateStudentData;
use App\Domain\SchoolCore\Students\Data\StudentReadModel;

interface StudentServiceContract
{
    public function create(SchoolContext $context, CreateStudentData $data): StudentReadModel;

    public function update(SchoolContext $context, int $studentId, UpdateStudentData $data): StudentReadModel;

    public function find(SchoolContext $context, int $studentId): ?StudentReadModel;

    public function archive(SchoolContext $context, int $studentId, string $reason): void;
}
```

### Student Identifier Generation

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface StudentIdentifierGeneratorContract
{
    public function generate(SchoolContext $context, int $studentId): string;
}
```

### Guardians

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Guardians\Data\GuardianRelationshipData;

interface GuardianServiceContract
{
    public function attachGuardian(SchoolContext $context, int $studentId, GuardianRelationshipData $data): void;

    public function detachGuardian(SchoolContext $context, int $studentId, int $guardianId): void;

    public function listForStudent(SchoolContext $context, int $studentId): array;
}
```

### Enrollment

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Enrollment\Data\EnrollmentData;

interface EnrollmentServiceContract
{
    public function enroll(SchoolContext $context, int $studentId, EnrollmentData $data): void;

    public function transfer(SchoolContext $context, int $studentId, EnrollmentData $data): void;

    public function withdraw(SchoolContext $context, int $studentId, string $reason): void;
}
```

### Attendance

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Attendance\Data\AttendanceMarkData;
use App\Domain\SchoolCore\Attendance\Data\AttendanceScanData;
use App\Domain\SchoolCore\Attendance\Data\AttendanceResult;

interface AttendanceServiceContract
{
    public function markStudent(SchoolContext $context, AttendanceMarkData $data): AttendanceResult;

    public function processScan(SchoolContext $context, AttendanceScanData $data): AttendanceResult;

    public function summarizeDay(SchoolContext $context, string $date): array;
}
```

### Attendance Policy

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use DateTimeInterface;

interface AttendancePolicyContract
{
    public function isSchoolDay(SchoolContext $context, DateTimeInterface $date): bool;

    public function determineStatus(SchoolContext $context, DateTimeInterface $scanTime, array $session): string;

    public function duplicateScanWindowSeconds(SchoolContext $context): int;
}
```

### Academic Calendar

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use DateTimeInterface;

interface AcademicCalendarProviderContract
{
    public function currentAcademicYear(SchoolContext $context): ?int;

    public function currentTerm(SchoolContext $context): ?int;

    public function sessionsForDate(SchoolContext $context, DateTimeInterface $date): array;
}
```

### Academics

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface GradeScalePolicyContract
{
    public function gradeForScore(SchoolContext $context, float $score): string;

    public function passingScore(SchoolContext $context): float;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface PromotionPolicyContract
{
    public function canPromote(SchoolContext $context, int $studentId): bool;

    public function nextPlacement(SchoolContext $context, int $studentId): array;
}
```

### Finance

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Finance\Data\CreateInvoiceData;
use App\Domain\SchoolCore\Finance\Data\InvoiceReadModel;

interface InvoiceServiceContract
{
    public function create(SchoolContext $context, CreateInvoiceData $data): InvoiceReadModel;

    public function recalculate(SchoolContext $context, int $invoiceId): InvoiceReadModel;

    public function find(SchoolContext $context, int $invoiceId): ?InvoiceReadModel;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Finance\Data\RecordPaymentData;
use App\Domain\SchoolCore\Finance\Data\EditPaymentData;
use App\Domain\SchoolCore\Finance\Data\PaymentReadModel;

interface PaymentServiceContract
{
    public function record(SchoolContext $context, RecordPaymentData $data): PaymentReadModel;

    public function edit(SchoolContext $context, int $paymentId, EditPaymentData $data): PaymentReadModel;

    public function void(SchoolContext $context, int $paymentId, string $reason): void;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface PaymentAllocationPolicyContract
{
    public function allocate(SchoolContext $context, int $invoiceId, float $amount): array;
}
```

### Files

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface FileAccessPolicyContract
{
    public function canAccess(SchoolContext $context, string $filePurpose, int $ownerId, array $metadata = []): bool;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface FileStorageServiceContract
{
    public function store(SchoolContext $context, string $purpose, mixed $file, array $metadata = []): string;

    public function resolvePath(SchoolContext $context, string $fileReference): string;

    public function delete(SchoolContext $context, string $fileReference): void;
}
```

### Communication

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Communication\Data\MessageData;
use App\Domain\SchoolCore\Communication\Data\RecipientQuery;

interface CommunicationServiceContract
{
    public function previewRecipients(SchoolContext $context, RecipientQuery $query): array;

    public function send(SchoolContext $context, MessageData $message): array;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;
use App\Domain\SchoolCore\Communication\Data\RecipientQuery;

interface RecipientResolverContract
{
    public function resolve(SchoolContext $context, RecipientQuery $query): array;
}
```

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface CommunicationPreferencePolicyContract
{
    public function mayContact(SchoolContext $context, int $recipientId, string $channel, string $purpose): bool;
}
```

### Reporting

```php
namespace App\Domain\SchoolCore\Contracts;

use App\Domain\SchoolCore\Context\SchoolContext;

interface ReportServiceContract
{
    public function generate(SchoolContext $context, string $reportKey, array $filters = []): array;
}
```

## DTO and Read Model Rules

Create DTOs only where contracts need them. Do not invent DTOs for every two-field method just to feel enterprise.

Recommended naming:

```text
CreateStudentData
UpdateStudentData
StudentReadModel
AttendanceMarkData
AttendanceScanData
AttendanceResult
CreateInvoiceData
RecordPaymentData
EditPaymentData
PaymentReadModel
MessageData
RecipientQuery
```

Rules:

- DTOs must be immutable where practical.
- DTOs must be created from validated request data, not raw request data.
- DTOs must not call the database.
- Read models must not expose sensitive fields by default.
- Read models must include `school_id` only when needed for authorization/debugging, not casually leaked in every response.

## Service Provider Bindings

Create `SchoolCoreServiceProvider`.

```php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Domain\SchoolCore\Contracts\StudentServiceContract;
use App\Domain\SchoolCore\Students\Services\StudentService;

class SchoolCoreServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(StudentServiceContract::class, StudentService::class);
        // Bind additional core contracts as implementations are introduced.
    }
}
```

Create `IslamicSundaySchoolServiceProvider` for extension policies.

```php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Domain\SchoolCore\Contracts\AttendancePolicyContract;
use App\Domain\IslamicIslamicSundaySchool\Attendance\IslamicSundaySchoolAttendancePolicy;

class IslamicSundaySchoolServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(AttendancePolicyContract::class, IslamicSundaySchoolAttendancePolicy::class);
    }
}
```

Important: core contract bindings may point to core defaults. Islamic Sunday School may override only extension contracts/policies, not replace the entire platform unless a module-specific reason is documented.

## Binding Strategy

Use this three-level binding model:

### 1. Core service contracts

These are stable platform services.

Examples:

```text
StudentServiceContract → SchoolCore\Students\Services\StudentService
PaymentServiceContract → SchoolCore\Finance\Services\PaymentService
AttendanceServiceContract → SchoolCore\Attendance\Services\AttendanceService
```

### 2. Policy/provider contracts

These are extension points.

Examples:

```text
AttendancePolicyContract → IslamicSundaySchool\Attendance\IslamicSundaySchoolAttendancePolicy
AcademicCalendarProviderContract → IslamicSundaySchool\Providers\IslamicSundaySchoolCalendarProvider
PaymentAllocationPolicyContract → IslamicSundaySchool\Policies\IslamicSundaySchoolPaymentAllocationPolicy
```

### 3. Infrastructure contracts

These provide storage, messaging, and integration adapters.

Examples:

```text
FileStorageServiceContract → LaravelLocalFileStorageService
CommunicationServiceContract → LaravelCommunicationService
```

## First Migration Slice: Student Identifier Generation

This is the safest first slice because it fixes a real design bug without moving the whole student module.

### Current Problem

Student creation currently risks race conditions when identifiers are generated using `max(id) + 1` before the student row is safely persisted.

### Target Design

```text
StudentController
  → CreateStudentRequest
  → CreateStudentData
  → StudentServiceContract
  → StudentService
  → StudentIdentifierGeneratorContract
```

### Tasks

1. Create `StudentIdentifierGeneratorContract`.
2. Create default implementation: `SequentialStudentIdentifierGenerator`.
3. Generate identifier after student insert using the persisted student ID.
4. Add unique database constraint for `(school_id, school_id_number)` or equivalent identifier column.
5. Add retry behavior for collisions.
6. Add concurrent creation test.
7. Keep the existing API response compatible.

### Acceptance Criteria

- Two concurrent student creations cannot produce the same identifier.
- Student ID format can be changed by binding a different generator.
- Islamic Sunday School-specific identifier formatting does not live inside core student creation logic.
- Existing student creation endpoint still works.

## Second Migration Slice: Payment File Access Policy

This slice validates that contracts can enforce security boundaries.

### Current Problem

Filename-based file serving risks unauthorized access if a user can guess a payment file name.

### Target Design

```text
PaymentManualController
  → PaymentFileDownloadRequest
  → PaymentServiceContract or PaymentFileService
  → FileAccessPolicyContract
  → FileStorageServiceContract
```

### Tasks

1. Create `FileAccessPolicyContract`.
2. Create `PaymentFileAccessPolicy` implementation.
3. Replace filename-only lookup with payment-ID-based lookup.
4. Resolve file path from the payment record.
5. Authorize against school context and actor permissions.
6. Add audit log entry for file access.
7. Return `403` for unauthorized access.
8. Return `404` for missing file or missing payment.
9. Add tests for guessed filename access.

### Acceptance Criteria

- Users cannot download payment files by guessing filenames.
- Finance/admin users can download authorized payment files.
- Parents can only download files tied to their own financial records, if product rules allow parent access.
- Cross-school access fails.
- Payment file access uses `SchoolContext`.

## Third Migration Slice: Attendance Policy Stub

This slice prepares Phase 4 without fully extracting scanner logic yet.

### Target Design

```text
ScannerController
  → AttendanceServiceContract
  → AttendancePolicyContract
  → AcademicCalendarProviderContract
```

### Tasks

1. Create `AttendancePolicyContract`.
2. Create default `StandardSchoolAttendancePolicy`.
3. Create `IslamicSundaySchoolAttendancePolicy`.
4. Create `AcademicCalendarProviderContract`.
5. Create default provider.
6. Bind Islamic Sunday School provider in `IslamicSundaySchoolServiceProvider`.
7. Update scanner service extraction plan to call policies instead of hardcoded date/session assumptions.

### Acceptance Criteria

- Islamic Sunday School program attendance logic lives outside core.
- Attendance duplicate window is policy-driven.
- Scanner code can call a policy without knowing the school type.

## Controller Dependency Rule

New or touched controllers should depend on contracts, not concrete domain services.

Good:

```php
public function __construct(private StudentServiceContract $students) {}
```

Bad:

```php
public function __construct(private IslamicSundaySchoolStudentService $students) {}
```

Also bad:

```php
public function store(Request $request)
{
    $schoolId = auth()->user()->school_id;
    // 120 lines of student creation logic
}
```

Because apparently controllers become landfill if left unsupervised.

## Architecture Tests

Add architecture tests using one of these approaches:

- Pest architecture tests if Pest is available.
- PHPUnit custom tests scanning namespaces/imports.
- Static analysis rule in PHPStan/Larastan if already installed.

### Required Architecture Tests

#### `SchoolCore` must not import `IslamicSundaySchool`

```php
public function test_school_core_does_not_depend_on_islamic_sunday_school(): void
{
    $files = glob(app_path('Domain/SchoolCore/**/*.php'));

    foreach ($files as $file) {
        $contents = file_get_contents($file);
        $this->assertStringNotContainsString('App\\Domain\\IslamicSundaySchool', $contents, $file);
    }
}
```

#### Domain services must not use raw request

```php
public function test_domain_services_do_not_depend_on_http_request(): void
{
    $files = glob(app_path('Domain/**/*.php'));

    foreach ($files as $file) {
        $contents = file_get_contents($file);
        $this->assertStringNotContainsString('Illuminate\\Http\\Request', $contents, $file);
    }
}
```

#### Domain services must not call `auth()`

```php
public function test_domain_services_do_not_call_auth_helper(): void
{
    $files = glob(app_path('Domain/**/*.php'));

    foreach ($files as $file) {
        $contents = file_get_contents($file);
        $this->assertStringNotContainsString('auth()', $contents, $file);
    }
}
```

#### Core contracts must be neutral

Search contract names and method names for Islamic Sunday School vocabulary:

```text
masjid/community
ministry
sunday
bible
servant
service_day
```

Those words may appear in `IslamicSundaySchool`, not `SchoolCore`.

## Contract Review Checklist

Before approving a contract, answer:

- Is the name globally meaningful for any school?
- Does it require `SchoolContext`?
- Does it avoid `Request`?
- Does it avoid `auth()`?
- Does it avoid Eloquent leakage across module boundaries?
- Does it describe transaction ownership?
- Does it describe authorization expectations?
- Can Islamic Sunday School customize behavior without editing the contract?
- Can another school type use this contract without pretending to be a Islamic Sunday School?

## Implementation Tickets

### CC-001: Create Domain Namespace Skeleton

**Objective:** Create the folder and namespace structure for `SchoolCore`, `IslamicSundaySchool`, and `Shared`.

**Tasks:**

- Add directory structure.
- Add placeholder README files for each major module.
- Document dependency direction in `app/Domain/README.md`.

**Acceptance Criteria:**

- Namespace structure exists.
- Dependency rule is documented.
- No production behavior changes.

### CC-002: Create Core Contract Interfaces

**Objective:** Add first-pass contracts for students, attendance, finance, files, communication, academics, enrollment, and reporting.

**Tasks:**

- Add contracts under `App\Domain\SchoolCore\Contracts`.
- Add minimal DTO namespaces.
- Add docblocks for transaction and authorization expectations.

**Acceptance Criteria:**

- Contracts compile.
- Contracts use `SchoolContext`.
- Contracts do not mention Islamic Sunday School concepts.

### CC-003: Add Service Providers and Bindings

**Objective:** Bind contracts to initial implementations.

**Tasks:**

- Create `SchoolCoreServiceProvider`.
- Create `IslamicSundaySchoolServiceProvider`.
- Register providers.
- Bind first implementations.

**Acceptance Criteria:**

- Container resolves all initial contracts.
- Islamic Sunday School extension policies can override policy/provider contracts.
- Core service bindings remain neutral.

### CC-004: Add Architecture Boundary Tests

**Objective:** Prevent forbidden dependencies.

**Tasks:**

- Add tests for `SchoolCore -> IslamicSundaySchool` imports.
- Add tests preventing `Request` in domain services.
- Add tests preventing `auth()` in domain services.
- Add tests for forbidden vocabulary in `SchoolCore` contracts.

**Acceptance Criteria:**

- Tests fail when forbidden dependencies are introduced.
- Tests run in CI.

### CC-005: Migrate Student Identifier Generation Behind Contract

**Objective:** Fix student identifier race condition and introduce the first real core contract usage.

**Tasks:**

- Create `StudentIdentifierGeneratorContract`.
- Add default implementation.
- Update student creation flow.
- Add unique constraint.
- Add concurrency test.

**Acceptance Criteria:**

- No duplicate student identifiers under concurrent creation.
- Identifier format can be replaced by binding.
- Existing API response is preserved.

### CC-006: Migrate Payment File Access Behind Policy Contract

**Objective:** Use contract architecture to fix payment file authorization.

**Tasks:**

- Create `FileAccessPolicyContract`.
- Create payment-specific policy implementation.
- Replace filename-only access with payment-ID-based access.
- Add audit log.
- Add authorization tests.

**Acceptance Criteria:**

- Guessed filenames cannot access files.
- Cross-school file access fails.
- Authorized finance/admin access succeeds.

### CC-007: Add Attendance Policy Stub

**Objective:** Prepare attendance extraction by separating attendance rules from scanner implementation.

**Tasks:**

- Create `AttendancePolicyContract`.
- Create `AcademicCalendarProviderContract`.
- Add default and Islamic Sunday School implementations.
- Bind policy/provider implementations.

**Acceptance Criteria:**

- Islamic Sunday School attendance rules are outside `SchoolCore`.
- Scanner extraction can use contracts in Phase 4.

## Phase 2 Rollout Order

Use this order:

1. Create namespace skeleton.
2. Add core contracts.
3. Add DTO/read model skeletons.
4. Add providers and empty bindings.
5. Add architecture tests.
6. Migrate student identifier generation.
7. Migrate payment file access.
8. Add attendance policy stub.
9. Update modular platform plan with completed contracts.

## Phase 2 Done Definition

Phase 2 is complete when:

- Core contracts exist and compile.
- Initial service providers are registered.
- `SchoolCore` cannot depend on `IslamicSundaySchool` without failing tests.
- Domain services cannot use `Request` or `auth()` without failing tests.
- Student identifier generation is contract-based and race-safe.
- Payment file access uses policy-based authorization.
- Attendance has policy/provider contracts ready for extraction.
- Islamic Sunday School behavior is expressed through extension contracts, not hardcoded core logic.

## Risks

### Risk: Too many contracts too early

Mitigation: only create contracts that are needed by migration slices. Keep method count small.

### Risk: Interfaces mirror bad legacy services

Mitigation: design contracts around platform capabilities, not current class names.

### Risk: Islamic Sunday School rules leak into core

Mitigation: forbidden vocabulary tests and provider-based extension points.

### Risk: Controllers keep calling old services

Mitigation: each touched controller must move toward contract injection.

### Risk: DTO explosion

Mitigation: create DTOs for cross-module payloads only. Do not manufacture object bureaucracy for two strings and a prayer.

## Non-Goals

Phase 2 does not fully refactor finance, attendance, students, communication, or reporting.

Phase 2 does not remove every legacy service.

Phase 2 does not redesign every database table.

Phase 2 creates the contract layer and proves the boundary works through a few real migration slices.

## Final Notes

This phase must be boring on purpose. Contracts are not where creativity belongs. They are where the platform decides what it promises and what it refuses to know.

The most important rule: `SchoolCore` must remain generic. Islamic Sunday School extends it. It does not secretly define it.
