Describe the bug
On Windows, creating a persistent REST cursor signing key can silently change its bytes. The Server initially starts successfully, but a subsequent start fails with ValueError: cursor signing key must contain 32 bytes.
src/powercontext/server/cursor_secret.py opens the key with os.open without O_BINARY. Windows text-mode writes translate each LF byte into CRLF. Generated keys containing LF are therefore longer on disk than the 32-byte value used by the first process. The binary reader rejects the file on restart.
This is a Server persistence defect introduced in #1438, found by the native Windows lifecycle check on #1459. It is independent of the DSH automatic-path changes. It affects both the file-backed SQLite key and the locally persisted key used without an explicit secret for other database configurations.
Steps to reproduce
On Windows at upstream commit fc75f9270cf4b493411e1c3bef9965bd3b313edb, with the development dependencies installed, run:
from pathlib import Path
from tempfile import TemporaryDirectory
from unittest.mock import patch
from powercontext.builtin.persistence.sqlite import SQLiteConfig
from powercontext.server.cursor_secret import resolve_cursor_secret
with TemporaryDirectory() as directory:
root = Path(directory)
database = SQLiteConfig(url=f"sqlite+aiosqlite:///{root / 'powercontext.db'}")
with patch("powercontext.server.cursor_secret.secrets.token_bytes", return_value=bytes(range(32))):
resolve_cursor_secret(database, None)
print((root / ".powercontext.db.cursor-key").stat().st_size)
resolve_cursor_secret(database, None)
The fixed input includes LF, making the failure deterministic. It changes neither filesystem access nor repository permissions and does not require a model or external database.
Expected behavior
The persisted key contains exactly the generated 32 bytes. The Server can restart and accept pagination cursors issued before the restart.
Actual behavior
The reproduction prints 33 and the next read raises the length validation error. The existing Server restart test also fails deterministically when its generated key contains LF.
Native Windows CI failure, artifact windows-native-service-logs, contains:
16:26:31 PowerContext Server is ready
16:26:42 Started server process [2248]
ValueError: cursor signing key must contain 32 bytes: .../.powercontext.db.cursor-key
Application startup failed. Exiting.
The test assertion only reported an unreachable service. Randomly generated keys without LF avoid the defect, so rerunning can hide it without fixing it.
Environment
Are you willing to submit a PR to fix this bug?
Describe the bug
On Windows, creating a persistent REST cursor signing key can silently change its bytes. The Server initially starts successfully, but a subsequent start fails with
ValueError: cursor signing key must contain 32 bytes.src/powercontext/server/cursor_secret.pyopens the key withos.openwithoutO_BINARY. Windows text-mode writes translate each LF byte into CRLF. Generated keys containing LF are therefore longer on disk than the 32-byte value used by the first process. The binary reader rejects the file on restart.This is a Server persistence defect introduced in #1438, found by the native Windows lifecycle check on #1459. It is independent of the DSH automatic-path changes. It affects both the file-backed SQLite key and the locally persisted key used without an explicit secret for other database configurations.
Steps to reproduce
On Windows at upstream commit
fc75f9270cf4b493411e1c3bef9965bd3b313edb, with the development dependencies installed, run:The fixed input includes LF, making the failure deterministic. It changes neither filesystem access nor repository permissions and does not require a model or external database.
Expected behavior
The persisted key contains exactly the generated 32 bytes. The Server can restart and accept pagination cursors issued before the restart.
Actual behavior
The reproduction prints
33and the next read raises the length validation error. The existing Server restart test also fails deterministically when its generated key contains LF.Native Windows CI failure, artifact
windows-native-service-logs, contains:The test assertion only reported an unreachable service. Randomly generated keys without LF avoid the defect, so rerunning can hide it without fixing it.
Environment
fc75f927after feat(api): implement source and artifact base REST APIs #1438; also present in fix(dsh): complete automatic-path diagnostics and recall presentation #1459 ate3ad78d7.windows-latest, Python 3.12.10, fresh wheel installation withcli,serverextras.Are you willing to submit a PR to fix this bug?