Files

4.7 KiB

Business Rules — Unit 2: slave-availability-extension

Rule Set 1: API Key Validation

graph TD
    A{Registration\nexists in DB?} -->|No| B{Is this a\nregister call?}
    B -->|Yes| C[Accept and create\nnew registration]
    B -->|No| D[Return 401\nUnauthorized]
    A -->|Yes| E{X-Master-Api-Key\nmatches stored key?}
    E -->|Yes| F[Proceed with\nbusiness logic]
    E -->|No| G[Return 401\nUnauthorized]

    classDef decision fill:#FFC107,stroke:#F57F17,color:#000
    classDef pass fill:#9ae6b4,stroke:#2f855a,color:#000
    classDef fail fill:#FC8181,stroke:#C53030,color:#000

    class A,B,E decision
    class C,F pass
    class D,G fail

Text alternative: If no registration exists and this is a register call, create it. If no registration and not a register call, 401. If registration exists, validate key; match = proceed, mismatch = 401.

Validation rules:

# Rule Applies to
BR-SLAVE-01 First POST /register with no existing registration: accept unconditionally, store ApiKey from X-Master-Api-Key header Register endpoint
BR-SLAVE-02 Subsequent POST /register: validate header against stored ApiKey. Match → update MasterUrl + LastContactedAt. Mismatch → 401. Register endpoint
BR-SLAVE-03 POST /status without existing registration → 401 Status push endpoint
BR-SLAVE-04 POST /status with key mismatch → 401 Status push endpoint
BR-SLAVE-05 GET /registered-url without existing registration → 401 Get-URL endpoint
BR-SLAVE-06 GET /registered-url with key mismatch → 401 Get-URL endpoint
BR-SLAVE-07 Missing or empty X-Master-Api-Key header → 401 on all endpoints All master endpoints

Rule Set 2: Master Gate Bypass

graph TD
    A{Path starts with\nbypass prefix?} -->|Yes| B[Pass through\nunconditionally]
    A -->|No| C{Valid admin\nJWT bearer?}
    C -->|Yes| B
    C -->|No| D{Master gate\nenabled?}
    D -->|_masterIsAvailable = true\nor default| E[Proceed to\nlocal gate]
    D -->|_masterIsAvailable = false| F[Return 503\nwith master message]
    E --> G{Local availability\ncheck}
    G -->|Available| H[Pass to next\nmiddleware]
    G -->|Unavailable| I[Return 503\nwith local message]

    classDef decision fill:#FFC107,stroke:#F57F17,color:#000
    classDef pass fill:#9ae6b4,stroke:#2f855a,color:#000
    classDef fail fill:#FC8181,stroke:#C53030,color:#000

    class A,C,D,G decision
    class B,E,H pass
    class F,I fail

Text alternative: Bypass path check first. Admin JWT next (bypasses both gates). Then master gate (static field). If master blocks: 503. If master passes: local gate. If local blocks: 503. Otherwise pass through.

Bypass prefix list (extended from existing):

Path prefix Reason
/api/v1/Availability/status Already bypassed — public status endpoint
/api/v1/Auth/ Already bypassed — login must always work
/api/v1/Setup/status Already bypassed — frontend init check
/api/v1/master/ NEW — master management endpoints must bypass gate so master can always push status or re-register

Cache behavior rules:

# Rule
BR-SLAVE-08 _masterIsAvailable defaults to true (fail-open) on process startup
BR-SLAVE-09 _masterDisableMessage defaults to null on process startup
BR-SLAVE-10 Cache has no expiry (Q4=A); only updated on POST /status with valid API key
BR-SLAVE-11 503 response from master gate includes _masterDisableMessage in ProblemDetails.Detail

Rule Set 3: MasterRegistration Singleton

# Rule
BR-SLAVE-12 MasterRegistration is a singleton: Id is always Guid.Parse("00000000-0000-0000-0000-000000000001")
BR-SLAVE-13 On RegisterAsync: if row with that Id exists → update. If not → insert. Never delete.
BR-SLAVE-14 RegisteredAt is set once at creation and never updated
BR-SLAVE-15 LastContactedAt is updated on every successful master call (register, status push, get-url)

Rule Set 4: Controller Routing

Endpoint Method Route Auth
Register master POST /api/v1/master/register None (API key in header)
Receive status push POST /api/v1/master/status None (API key in header)
Get registered URL GET /api/v1/master/registered-url None (API key in header)

All three endpoints are unauthenticated from ASP.NET Core's perspective — they use the custom X-Master-Api-Key header validation implemented in MasterAvailabilityService. They are also in the middleware bypass list so the gate cannot block master management calls.