""" TDD scaffold for Phase 7.3: ES256 algorithm upgrade, startup token rotation, and remember_me session TTL — all stubs xfail strict=True until promoted. """ from __future__ import annotations import base64 import hashlib import json import time import uuid from datetime import datetime, timedelta, timezone import pytest import pytest_asyncio # ── ES256 key fixture ──────────────────────────────────────────────────────── @pytest.fixture(autouse=True) def es256_keys(monkeypatch): """Generate a throw-away P-256 keypair and monkeypatch it into settings. raising=False: settings fields do not exist until Plan 02 adds them; this fixture must not error before that. """ from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import serialization private_key = ec.generate_private_key(ec.SECP256R1()) private_pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) public_pem = private_key.public_key().public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo, ) private_b64 = base64.b64encode(private_pem).decode() public_b64 = base64.b64encode(public_pem).decode() import config monkeypatch.setattr(config.settings, "jwt_private_key", private_b64, raising=False) monkeypatch.setattr(config.settings, "jwt_public_key", public_b64, raising=False) # ── ES256-01: access token algorithm ───────────────────────────────────────── @pytest.mark.xfail(strict=True, reason="ES256-01: not yet implemented") def test_access_token_uses_es256(): pytest.xfail("not yet implemented") # ── ES256-02: HS256 token rejected ─────────────────────────────────────────── @pytest.mark.xfail(strict=True, reason="ES256-02: not yet implemented") def test_hs256_token_rejected(): pytest.xfail("not yet implemented") # ── ES256-03: password-reset token algorithm ────────────────────────────────── @pytest.mark.xfail(strict=True, reason="ES256-03: not yet implemented") def test_reset_token_uses_es256(): pytest.xfail("not yet implemented") # ── ES256-04: startup rotation revokes tokens ───────────────────────────────── @pytest.mark.xfail(strict=True, reason="ES256-04: not yet implemented") @pytest.mark.asyncio async def test_startup_rotation_revokes_tokens(db_session): pytest.xfail("not yet implemented") # ── ES256-05: startup rotation is idempotent ───────────────────────────────── @pytest.mark.xfail(strict=True, reason="ES256-05: not yet implemented") @pytest.mark.asyncio async def test_startup_rotation_idempotent(db_session): pytest.xfail("not yet implemented") # ── RM-01: default TTL is 16 hours ─────────────────────────────────────────── @pytest.mark.xfail(strict=True, reason="RM-01: not yet implemented") @pytest.mark.asyncio async def test_default_ttl_16_hours(async_client, db_session, auth_user): pytest.xfail("not yet implemented") # ── RM-02: remember_me TTL is 30 days ──────────────────────────────────────── @pytest.mark.xfail(strict=True, reason="RM-02: not yet implemented") @pytest.mark.asyncio async def test_remember_me_ttl_30_days(async_client, db_session, auth_user): pytest.xfail("not yet implemented") # ── RM-03: cookie Max-Age values ───────────────────────────────────────────── @pytest.mark.xfail(strict=True, reason="RM-03: not yet implemented") @pytest.mark.asyncio async def test_remember_me_cookie_max_age(async_client, auth_user): pytest.xfail("not yet implemented") # ── CFG-01 satellite: settings has jwt key fields ──────────────────────────── @pytest.mark.xfail(strict=True, reason="CFG-01: not yet implemented") def test_settings_has_jwt_keys(): pytest.xfail("not yet implemented")