Stage 3 of the realism migration. Replaces orchestrator/scheduler.py's
hardcoded _FILE_TEMPLATES/_USERS (3 templates emitting epoch-suffixed
filenames like notes-1777315854.txt with identical bodies per
template) with a persona-driven realism engine.
New surface:
- SyntheticFile SQLModel (synthetic_files table, UNIQUE on
decky_uuid+path) — per-(decky, path) state for the future
edit-in-place flow. Pre-v1, no _migrate_* helper.
- BaseRepository methods: record_synthetic_file,
update_synthetic_file, list_synthetic_files,
pick_random_synthetic_file_for_edit (used by stage 3b).
- realism/naming.py: per-content-class filename templates,
persona-conditioned. /var/log/cron.log + logrotate skeleton for
system-class; /home/<persona>/TODO.md, scratch.md, etc. for
user-class. Anti-regression test pins "no 8+ digit decimals in
basenames" (the realism failure today).
- realism/bodies.py: deterministic body templates per content_class.
TODO body uses checkbox markdown, script body has a shebang, cron
body matches syslog cron shape ("CRON[PID]: (user) CMD (...)").
- realism/planner.py: pick(deckies, now, rng) returns a Plan.
Diurnal-gated, weighted user/system content split (70/30 user
bias). Create-only in stage 3; edit branch lands in stage 3b.
Scheduler split:
- scheduler.pick is now traffic-only (sync).
- scheduler.pick_file is async, takes a repo, resolves personas
(Topology.email_personas for topology-source deckies; global
realism.personas_pool otherwise), and maps Plan -> FileAction.
- FileAction gains persona/content_class/mtime fields.
Worker:
- _one_tick rolls 50/50 between traffic and file each tick. After a
successful FileAction plant, _record_synthetic_file persists or
patches the synthetic_files row (catching the unique-constraint
collision on re-plant of the same path).
- SSHDriver._run_file passes action.mtime through to plant_file so
files don't all stamp at wall-clock-now.
318 lines
6.7 KiB
Python
318 lines
6.7 KiB
Python
"""
|
|
Database tables (SQLModel) and HTTP request/response shapes (Pydantic).
|
|
|
|
Split into topical modules for readability, but every symbol is re-exported
|
|
from this package so ``from decnet.web.db.models import X`` keeps working
|
|
everywhere — no importer needs to know which submodule a class lives in.
|
|
"""
|
|
from ._base import (
|
|
NullableDatetime,
|
|
NullableString,
|
|
_BIG_TEXT,
|
|
_normalize_null,
|
|
)
|
|
from .common import (
|
|
MessageResponse,
|
|
)
|
|
from .canary import (
|
|
CanaryBlob,
|
|
CanaryBlobResponse,
|
|
CanaryBlobsResponse,
|
|
CanaryKind,
|
|
CanaryState,
|
|
CanaryToken,
|
|
CanaryTokenCreateRequest,
|
|
CanaryTokenResponse,
|
|
CanaryTokensResponse,
|
|
CanaryTrigger,
|
|
CanaryTriggerResponse,
|
|
CanaryTriggersResponse,
|
|
)
|
|
from .auth import (
|
|
AdminConfigResponse,
|
|
ChangePasswordRequest,
|
|
ConfigResponse,
|
|
CreateUserRequest,
|
|
DeploymentLimitRequest,
|
|
GlobalMutationIntervalRequest,
|
|
LoginRequest,
|
|
ResetUserPasswordRequest,
|
|
Token,
|
|
UpdateUserRoleRequest,
|
|
User,
|
|
UserResponse,
|
|
)
|
|
from .attackers import (
|
|
Attacker,
|
|
AttackerBehavior,
|
|
AttackerIdentity,
|
|
AttackersResponse,
|
|
SessionProfile,
|
|
SmtpTarget,
|
|
)
|
|
from .attacker_intel import (
|
|
AttackerIntel,
|
|
)
|
|
from .campaigns import (
|
|
Campaign,
|
|
CampaignsResponse,
|
|
)
|
|
from .deploy import (
|
|
DeployIniRequest,
|
|
DeployResponse,
|
|
MutateIntervalRequest,
|
|
PurgeResponse,
|
|
)
|
|
from .fleet import (
|
|
LOCAL_HOST_SENTINEL,
|
|
FleetDecky,
|
|
)
|
|
from .health import (
|
|
ComponentHealth,
|
|
HealthResponse,
|
|
)
|
|
from .orchestrator import (
|
|
OrchestratorEmail,
|
|
OrchestratorEmailsResponse,
|
|
OrchestratorEvent,
|
|
OrchestratorEventsResponse,
|
|
)
|
|
from .realism import (
|
|
SyntheticFile,
|
|
SyntheticFilesResponse,
|
|
)
|
|
from .logs import (
|
|
Bounty,
|
|
BountyResponse,
|
|
Credential,
|
|
CredentialReuse,
|
|
CredentialReuseResponse,
|
|
CredentialsResponse,
|
|
Log,
|
|
LogsResponse,
|
|
State,
|
|
StatsResponse,
|
|
)
|
|
from .swarm import (
|
|
DeckyShard,
|
|
DeckyShardView,
|
|
SwarmCheckResponse,
|
|
SwarmDeployRequest,
|
|
SwarmDeployResponse,
|
|
SwarmEnrolledBundle,
|
|
SwarmEnrollRequest,
|
|
SwarmHost,
|
|
SwarmHostHealth,
|
|
SwarmHostResult,
|
|
SwarmHostView,
|
|
SwarmTeardownRequest,
|
|
SwarmUpdaterBundle,
|
|
)
|
|
from .topology import (
|
|
LAN,
|
|
ArchetypeCatalogResponse,
|
|
ArchetypeEntry,
|
|
DeckyCreateRequest,
|
|
DeckyRow,
|
|
DeckyUpdateRequest,
|
|
DeployAcceptedResponse,
|
|
EdgeCreateRequest,
|
|
EdgeRow,
|
|
LANCreateRequest,
|
|
LANRow,
|
|
LANUpdateRequest,
|
|
MutationEnqueueRequest,
|
|
MutationEnqueueResponse,
|
|
MutationRow,
|
|
NextIPResponse,
|
|
NextSubnetResponse,
|
|
NotEditableResponse,
|
|
ReapReportResponse,
|
|
ServiceCatalogResponse,
|
|
Topology,
|
|
TopologyDecky,
|
|
TopologyDetail,
|
|
TopologyEdge,
|
|
TopologyGenerateRequest,
|
|
TopologyListResponse,
|
|
TopologyMutation,
|
|
TopologyStatusEvent,
|
|
TopologyStatusEventRow,
|
|
TopologySummary,
|
|
ValidationErrorResponse,
|
|
ValidationIssueResponse,
|
|
VersionConflictResponse,
|
|
)
|
|
from .updater import (
|
|
HostReleaseInfo,
|
|
HostReleasesResponse,
|
|
PushUpdateRequest,
|
|
PushUpdateResponse,
|
|
PushUpdateResult,
|
|
RollbackRequest,
|
|
RollbackResponse,
|
|
)
|
|
from .webhooks import (
|
|
SimpleEvent,
|
|
WebhookCreateRequest,
|
|
WebhookCreateResponse,
|
|
WebhookResponse,
|
|
WebhookSubscription,
|
|
WebhookTestResponse,
|
|
WebhookUpdateRequest,
|
|
)
|
|
from .workers import (
|
|
StartAllResponse,
|
|
StartFailure,
|
|
WorkerControlResponse,
|
|
WorkersResponse,
|
|
WorkerStatus,
|
|
)
|
|
|
|
__all__ = [
|
|
# _base
|
|
"NullableDatetime",
|
|
"NullableString",
|
|
"_BIG_TEXT",
|
|
"_normalize_null",
|
|
# common
|
|
"MessageResponse",
|
|
# canary
|
|
"CanaryBlob",
|
|
"CanaryBlobResponse",
|
|
"CanaryBlobsResponse",
|
|
"CanaryKind",
|
|
"CanaryState",
|
|
"CanaryToken",
|
|
"CanaryTokenCreateRequest",
|
|
"CanaryTokenResponse",
|
|
"CanaryTokensResponse",
|
|
"CanaryTrigger",
|
|
"CanaryTriggerResponse",
|
|
"CanaryTriggersResponse",
|
|
# auth
|
|
"AdminConfigResponse",
|
|
"ChangePasswordRequest",
|
|
"ConfigResponse",
|
|
"CreateUserRequest",
|
|
"DeploymentLimitRequest",
|
|
"GlobalMutationIntervalRequest",
|
|
"LoginRequest",
|
|
"ResetUserPasswordRequest",
|
|
"Token",
|
|
"UpdateUserRoleRequest",
|
|
"User",
|
|
"UserResponse",
|
|
# attackers
|
|
"Attacker",
|
|
"AttackerBehavior",
|
|
"AttackerIdentity",
|
|
"AttackerIntel",
|
|
"AttackersResponse",
|
|
"SessionProfile",
|
|
"SmtpTarget",
|
|
# campaigns
|
|
"Campaign",
|
|
"CampaignsResponse",
|
|
# deploy
|
|
"DeployIniRequest",
|
|
"DeployResponse",
|
|
"MutateIntervalRequest",
|
|
"PurgeResponse",
|
|
# fleet
|
|
"LOCAL_HOST_SENTINEL",
|
|
"FleetDecky",
|
|
# health
|
|
"ComponentHealth",
|
|
"HealthResponse",
|
|
# orchestrator
|
|
"OrchestratorEmail",
|
|
"OrchestratorEmailsResponse",
|
|
"OrchestratorEvent",
|
|
"OrchestratorEventsResponse",
|
|
# realism
|
|
"SyntheticFile",
|
|
"SyntheticFilesResponse",
|
|
# logs
|
|
"Bounty",
|
|
"BountyResponse",
|
|
"Credential",
|
|
"CredentialReuse",
|
|
"CredentialReuseResponse",
|
|
"CredentialsResponse",
|
|
"Log",
|
|
"LogsResponse",
|
|
"State",
|
|
"StatsResponse",
|
|
# swarm
|
|
"DeckyShard",
|
|
"DeckyShardView",
|
|
"SwarmCheckResponse",
|
|
"SwarmDeployRequest",
|
|
"SwarmDeployResponse",
|
|
"SwarmEnrolledBundle",
|
|
"SwarmEnrollRequest",
|
|
"SwarmHost",
|
|
"SwarmHostHealth",
|
|
"SwarmHostResult",
|
|
"SwarmHostView",
|
|
"SwarmTeardownRequest",
|
|
"SwarmUpdaterBundle",
|
|
# topology
|
|
"LAN",
|
|
"ArchetypeCatalogResponse",
|
|
"ArchetypeEntry",
|
|
"DeckyCreateRequest",
|
|
"DeckyRow",
|
|
"DeckyUpdateRequest",
|
|
"DeployAcceptedResponse",
|
|
"EdgeCreateRequest",
|
|
"EdgeRow",
|
|
"LANCreateRequest",
|
|
"LANRow",
|
|
"LANUpdateRequest",
|
|
"MutationEnqueueRequest",
|
|
"MutationEnqueueResponse",
|
|
"MutationRow",
|
|
"NextIPResponse",
|
|
"NextSubnetResponse",
|
|
"NotEditableResponse",
|
|
"ReapReportResponse",
|
|
"ServiceCatalogResponse",
|
|
"Topology",
|
|
"TopologyDecky",
|
|
"TopologyDetail",
|
|
"TopologyEdge",
|
|
"TopologyGenerateRequest",
|
|
"TopologyListResponse",
|
|
"TopologyMutation",
|
|
"TopologyStatusEvent",
|
|
"TopologyStatusEventRow",
|
|
"TopologySummary",
|
|
"ValidationErrorResponse",
|
|
"ValidationIssueResponse",
|
|
"VersionConflictResponse",
|
|
# updater
|
|
"HostReleaseInfo",
|
|
"HostReleasesResponse",
|
|
"PushUpdateRequest",
|
|
"PushUpdateResponse",
|
|
"PushUpdateResult",
|
|
"RollbackRequest",
|
|
"RollbackResponse",
|
|
# webhooks
|
|
"SimpleEvent",
|
|
"WebhookCreateRequest",
|
|
"WebhookCreateResponse",
|
|
"WebhookResponse",
|
|
"WebhookSubscription",
|
|
"WebhookTestResponse",
|
|
"WebhookUpdateRequest",
|
|
# workers
|
|
"StartAllResponse",
|
|
"StartFailure",
|
|
"WorkerControlResponse",
|
|
"WorkersResponse",
|
|
"WorkerStatus",
|
|
]
|