test(07.3-01): Wave 0 Nyquist scaffold — 9 xfail stubs for ES256 + remember_me
- Create test_auth_es256.py with 9 xfail(strict=True) stubs: ES256-01..05, RM-01..03, CFG-01 - Add es256_keys(autouse) fixture using cryptography P-256 keygen + monkeypatch with raising=False - Extend test_settings_has_jwt_config to assert refresh_token_expire_hours==16 + jwt key fields
This commit is contained in:
@@ -0,0 +1,123 @@
|
|||||||
|
"""
|
||||||
|
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")
|
||||||
@@ -29,6 +29,10 @@ def test_settings_has_jwt_config():
|
|||||||
assert settings.access_token_expire_minutes == 15
|
assert settings.access_token_expire_minutes == 15
|
||||||
assert hasattr(settings, "refresh_token_expire_days")
|
assert hasattr(settings, "refresh_token_expire_days")
|
||||||
assert settings.refresh_token_expire_days == 30
|
assert settings.refresh_token_expire_days == 30
|
||||||
|
assert hasattr(settings, "refresh_token_expire_hours")
|
||||||
|
assert settings.refresh_token_expire_hours == 16
|
||||||
|
assert hasattr(settings, "jwt_private_key")
|
||||||
|
assert hasattr(settings, "jwt_public_key")
|
||||||
|
|
||||||
|
|
||||||
def test_settings_has_smtp_config():
|
def test_settings_has_smtp_config():
|
||||||
|
|||||||
Reference in New Issue
Block a user