mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-09 07:09:51 +03:00
Refine scoped architecture guidance
Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
@@ -15,22 +15,23 @@
|
||||
|
||||
- Prefer the simplest design that makes ownership, state transitions, failure, and side effects explicit. Readability
|
||||
and one canonical path beat clever indirection or parallel implementations.
|
||||
- Keep policy close to the layer that owns it: models describe data, repositories persist it, services perform
|
||||
workflows, controllers own application state/orchestration, plugins/backends own protocol-specific behavior, and UI
|
||||
adapts those APIs.
|
||||
- Keep policy close to the layer that owns it: models describe data, repositories persist domain collections,
|
||||
`AppSettings` persists preferences, services perform workflows, controllers own shared runtime state/orchestration,
|
||||
plugins/backends own protocol-specific behavior, and UI adapts those APIs.
|
||||
- Make invalid states and boundary failures visible with specific return values, result objects, or exceptions. Catch
|
||||
broadly only at a genuine isolation boundary, log actionable context, and do not silently convert explicit user input
|
||||
into a different behavior.
|
||||
- Bound external work: network requests, subprocess startup/shutdown, thread joins, and host commands need timeouts or a
|
||||
documented non-GUI execution context. Cleanup must be idempotent and own exact resources, never search by process
|
||||
name.
|
||||
- Bound external work where the workflow requires responsiveness: network requests, subprocess startup/shutdown,
|
||||
thread joins, and host commands need caller-chosen timeouts or a documented non-GUI execution context. Low-level
|
||||
wrappers such as `runExternalCommand()` intentionally do not invent a universal timeout. Cleanup must be idempotent,
|
||||
own exact resources, and never search by process name.
|
||||
- Prefer immutable metadata, pure transformations, dependency injection, and explicit runtime copies. Avoid global
|
||||
mutable state, hidden mutation, duplicated caches, and UI-owned business state.
|
||||
|
||||
## Repository invariants
|
||||
|
||||
- Treat persisted user configuration as input. Connection, routing, testing, logging, and statistics preparation operate
|
||||
on explicit runtime copies unless an API is documented as mutating storage.
|
||||
- Treat persisted user configuration as input. Connection, routing, testing, logging, TUN, and statistics preparation
|
||||
must not mutate it implicitly; use explicit runtime/derived state unless an API is documented as mutating storage.
|
||||
- Prefer plugin capabilities/factories over protocol or core conditionals in shared managers. Registries store classes,
|
||||
factories, descriptors, and immutable metadata—not transient UI instances.
|
||||
- `CoreRuntime` means one managed proxy-core lifecycle regardless of whether its implementation uses a subprocess,
|
||||
|
||||
+4
-3
@@ -2,9 +2,10 @@
|
||||
|
||||
## Layering and state
|
||||
|
||||
- `Models` and `Interface` define core-neutral data and contracts. `Repository` owns persistence, `Service` owns
|
||||
workflows/resources, `Controllers` own shared application state, `Plugins`/`Backends` own protocol behavior, and
|
||||
`Application` composes the runtime. `Qt`, `Widget`, and `Window` present that state.
|
||||
- `Models` and `Interface` define core-neutral data and contracts. `Repository` owns persisted domain collections,
|
||||
`AppSettings` owns preferences, `Service` owns workflows/resources, `Controllers` own shared runtime state,
|
||||
`Plugins`/`Backends` own protocol behavior, and `Application` composes them. `Qt`, `Widget`, and `Window` present that
|
||||
state.
|
||||
- Existing UI code has compatibility paths that reach repositories or application globals. Do not extend that coupling
|
||||
when a controller/service API can be introduced cleanly; migrate incrementally rather than creating a second state
|
||||
authority.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Application composition guidance
|
||||
|
||||
- `DesktopApplication` is the composition root. It creates and durably owns application-lifetime controllers,
|
||||
repositories, services, pages, main window, tray, thread pool, IPC server, and plugin registry integration.
|
||||
- `DesktopApplication` is the composition root. It creates or acquires and durably owns application-lifetime
|
||||
controllers, repository access, services, pages, main window, tray, thread pool, singleton IPC endpoint, and plugin
|
||||
registry integration.
|
||||
- Keep bootstrap order explicit: environment/plugins and storage before consumers, controllers/services before UI, and
|
||||
restoration only after all dependencies exist. Accessors must tolerate partial startup and cleanup.
|
||||
- Each successful startup stage registers its exact cleanup immediately. Partial startup and final shutdown use the
|
||||
|
||||
Vendored
+2
-2
@@ -4,8 +4,8 @@
|
||||
or the translation data and regenerate.
|
||||
- Each catalog entry uses this key order: `source`, supported language keys in the generator's canonical order, then
|
||||
`isReviewed`.
|
||||
- `source` is a sorted, deduplicated list of fully qualified Python module names that contain the extracted source text.
|
||||
Remove stale sources through regeneration, not manual cleanup.
|
||||
- `source` is a deduplicated list of fully qualified Python module names discovered by the generator. Preserve generated
|
||||
ordering and remove stale sources through regeneration, not manual cleanup.
|
||||
- `_()`/`gettext()` extraction accepts static literals. The only f-string exception consists exclusively of bare names
|
||||
defined in `Furious.Frozenlib.Constants`; the extractor substitutes those values before catalog lookup.
|
||||
- Do not put runtime values, attribute expressions, calls, format specifications, `.format(...)`, or ordinary brace
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
## Platform and process safety
|
||||
|
||||
- Host mutation (proxy, DNS, startup registration, session, routing) is platform-isolated, returns/logs actionable
|
||||
failure, uses bounded commands/joins, and can be fully mocked. Never test against real host state.
|
||||
failure, and can be fully mocked. `runExternalCommand()` intentionally delegates timeout policy to each caller;
|
||||
callers that require bounded execution must pass a timeout or run in a documented non-GUI context. Never test against
|
||||
real host state.
|
||||
- Own exact daemon threads/processes. Clear dead references so restart is possible; cleanup is bounded and idempotent.
|
||||
Do not suppress a failed shutdown or leave persisted state claiming success.
|
||||
- `parseHostPort` and other externally keyed caches must be bounded. Unbounded caches are limited to finite application
|
||||
@@ -29,6 +31,7 @@
|
||||
|
||||
## Code review rules
|
||||
|
||||
- Flag GUI/high-level imports, unbounded host commands or joins, state persisted after host failure, broad process-name
|
||||
cleanup, sensitive logging, unbounded external-input caches, and globals holding transient objects.
|
||||
- Flag GUI/high-level imports, caller paths that can block the GUI or shutdown without an intentional bound, state
|
||||
persisted after host failure, broad process-name cleanup, sensitive logging, unbounded external-input caches, and
|
||||
globals holding transient objects. Do not add a universal timeout to `runExternalCommand()`.
|
||||
- Run direct mocked platform/helper tests plus affected controller/service tests.
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
callback order, serialization behavior, and bounded stop expectations.
|
||||
- Do not introduce mechanism-specific aliases for `CoreRuntime` or mistake the semantic runtime contract for an
|
||||
operating-system process.
|
||||
- Serialization uses the shared `Furious.Models` encoders. Preserve supported dict subclasses such as `CoreConfiguration`;
|
||||
return/raise behavior must be documented and failures must retain useful diagnostics.
|
||||
- Serialization uses the shared `Furious.Models` encoders. Preserve supported dict subclasses such as
|
||||
`CoreConfiguration`; return/raise behavior must be documented and failures must retain useful diagnostics.
|
||||
- Storage contracts intentionally expose live mutable collections. State that explicitly—do not label them copies—and
|
||||
keep persistence/ordering semantics in concrete repositories.
|
||||
- Editor bindings translate between widgets and configuration but do not decide process/runtime policy.
|
||||
|
||||
@@ -37,9 +37,10 @@ Use the `manage-qt-pyside6-lifetimes` skill for any Qt ownership or lifecycle ch
|
||||
|
||||
## Network replies and presentation
|
||||
|
||||
- Give each reply one manager/context owner, reject stale generations, handle success/error/abort exactly once, and call
|
||||
`deleteLater()` on every terminal path. Do not attach ad-hoc application attributes to third-party Qt objects when a
|
||||
manager mapping suffices.
|
||||
- Give each reply one manager/context owner. Where a newer request supersedes an older one, use a generation/version or
|
||||
equivalent identity check; independent requests do not need a synthetic generation. Handle success/error/abort once
|
||||
and call `deleteLater()` on every terminal path. Do not attach ad-hoc application attributes to third-party Qt
|
||||
objects when a manager mapping suffices.
|
||||
- Preserve keyboard, focus, shortcuts, accessibility, light/dark theme, layout responsiveness, and translated-text
|
||||
growth.
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Repository guidance
|
||||
|
||||
- Repositories are the only persistence authority for profiles, subscriptions, routing, and TUN settings. Keep
|
||||
Qt/UI/workflow concerns out of repository implementations.
|
||||
- Repositories are the persistence authority for domain collections and documents such as profiles, subscriptions,
|
||||
routing configurations, and TUN settings. Application preferences and current selections may use `AppSettings` at
|
||||
their owning controller/application boundary. Keep Qt/UI/workflow concerns out of repository implementations.
|
||||
- Preserve stable IDs, ordering, unknown compatible fields, legacy migrations, and subscription ownership. Display names
|
||||
and row indexes are not identities.
|
||||
- Subscription synchronization may update only profiles explicitly managed by that subscription and identified by stable
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
|
||||
## Async, network, and background work
|
||||
|
||||
- Each asynchronous request has an explicit generation/context. Partial results may publish independently, while
|
||||
stale/aborted replies are ignored and deleted exactly once.
|
||||
- Timeouts apply to network, DNS, executor, process, and host work. Executor callbacks must not retain a manager forever
|
||||
after shutdown; GUI updates cross via signals.
|
||||
- Each asynchronous workflow defines one explicit ownership and supersession policy: a generation/version where stale
|
||||
completion is possible, or exact reply/future ownership where requests are independent. Partial results may publish
|
||||
independently; terminal reply paths abort or finish once and schedule deletion once.
|
||||
- Bound network, DNS, process, host, and worker work where the provider permits it. Executor callbacks use weak or
|
||||
otherwise bounded ownership and must not retain a manager forever after shutdown; GUI updates cross via signals.
|
||||
- Logging and metrics collect while pages are hidden but avoid hidden-page rendering. Raw time-series samples are
|
||||
immutable; stable timestamp buckets are derived display data.
|
||||
- Log retention is owned by `LogManager`, not a text document. Category pruning/reset notifications must keep lazy UI
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
- Models, delegates, menus, actions, spinners, animations, timers, and network-backed helpers need explicit owners.
|
||||
Persistent page widgets are constructed once; refresh/show cycles toggle state rather than recreate/connect
|
||||
indefinitely.
|
||||
- Table selection operates on stable repository IDs, not visual rows after sort/filter. Keep model begin/end
|
||||
notifications, timer collections, and repository order synchronized.
|
||||
- Resolve table/list actions through the model mapping that is current after sort/filter. Use stable repository IDs for
|
||||
persisted or cross-refresh identity; preserve existing row-index compatibility only where the repository contract
|
||||
still requires it. Keep model begin/end notifications and repository ordering synchronized.
|
||||
- Use `AppQ*` controls and responsive layouts. Preserve translated-text growth, shortcuts, focus, accessibility, theme
|
||||
changes, high-DPI rendering, and hidden-page lazy behavior.
|
||||
- Expensive parsing, syntax highlighting, map/network work, metrics aggregation, and subscription synchronization must
|
||||
not freeze the GUI. Publish results through owned signals and reject stale generations.
|
||||
- Expensive parsing, map/network work, metrics aggregation, and subscription synchronization must not freeze the GUI.
|
||||
Batch, defer, or offload work according to the Qt API involved; publish worker results through owned signals and
|
||||
reject stale completions where requests can be superseded.
|
||||
- Transient editors/progress dialogs use managed `open()` lifetime; reusable top-level windows retain one explicit
|
||||
owner.
|
||||
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@
|
||||
event loop, request shutdown through the public path, and assert the child process exits normally. Repeat the cycle
|
||||
when the defect is intermittent.
|
||||
- A lifecycle child must be hermetic: bypass single-instance discovery and IPC, use temporary settings and application
|
||||
identity where relevant, disable tray and startup restoration, mock all host/network integrations, and never attach to,
|
||||
signal, inspect, or change a potentially running Furious instance.
|
||||
identity where relevant, disable tray and startup restoration, mock all host/network integrations, and never attach
|
||||
to, signal, inspect, or change a potentially running Furious instance.
|
||||
- Child-process tests own only the windows, threads, handles, and processes they create. Give every wait and child a
|
||||
bounded timeout, capture diagnostics, and terminate only that exact child on timeout. Never use process-name cleanup.
|
||||
- Visible diagnostic windows are for an explicit manual smoke procedure only. Automated tests always use the offscreen
|
||||
|
||||
Reference in New Issue
Block a user