Task
π **Task:** Build a `LoginIn` dataclass with `email: str` + `password: str` (write a `validate()` that raises `HTTPException` if email lacks '@' or password is shorter than 8 chars).
Build a `LoginOut` dataclass with `user_id: int` + `token: str`.
Build a `login(body: LoginIn) -> LoginOut` function that calls `body.validate()`, then returns `LoginOut(user_id=42, token=f'fake-{body.email}')`.
Build `healthz() -> str` returning `'ok'` and `readyz() -> str` returning `'ok'`.
Exercise: call `login(LoginIn('ada@example.com', 'supersecret'))` and print `.token`. Then call `login(LoginIn('bad', 'x'))` inside `try/except` and print the caught error message. Then call `healthz()` and `readyz()`.
Expected output (4 lines):
```
fake-ada@example.com
400: invalid login
ok
ok
```
π Implement the function above. Tests run automatically.
π‘ **Hint:** Re-read the theory if stuck.