Skip to main content

Project Structure

Workspace root

kienetic_assignment/ # workspace (not a Git repo itself)
├── documentation/ # this Docusaurus 3 site
│ ├── docs/{intro, guides, backend, frontend, shared}
│ ├── src/css/custom.css
│ ├── static/img
│ ├── docusaurus.config.ts
│ └── sidebars.ts # single 'docs' sidebar, generated-index categories
├── kxinspect_backend_python/ # independent Git repo
├── kxinspect_frontend_flutter/ # independent Git repo
├── UI/ # assignment screenshots (reference only)
├── plan.md # executable build plan (SPoT)
├── parts_plan.md
├── agent_prompts.md
└── run_backend.sh

The two app repos have separate histories, CIs and commit conventions. The frontend docs canonically link to a compatible backend SHA and vice-versa via docs/evidence/submission.yaml once publication is authorized (G-02). Root-level artefacts are not runtime dependencies.

Backend map

kxinspect_backend_python/
├── app/
│ ├── main.py # create_app() factory + build_app(explicit deps)
│ ├── core/
│ │ ├── config.py # Settings (pydantic-settings, KX_*), constants
│ │ ├── clock.py # Clock / Scheduler / ManualClock / SystemClock
│ │ ├── errors.py # ApiError hierarchy -> envelope
│ │ ├── ids.py # IdGenerator (UUID), deterministic for tests
│ │ ├── canonical_json.py # RFC 8785 canonicalization for idempotency digests
│ │ ├── graphemes.py # UAX #29 extended grapheme counting
│ │ ├── idempotency.py # require_key, scope_key, json/contest digest
│ │ └── chaos.py # latency/error injection behind KX_* toggles
│ ├── domain/
│ │ ├── charge_state.py # pure lifecycle: transition() total function
│ │ ├── deadline.py # deadlineAt = raisedAt + grace; isElapsed(now)
│ │ └── namespace.py # storage namespace helpers
│ ├── db/
│ │ ├── models.py # StoreSnapshot, Entities, StoredEvent, ENTITY_KEYS
│ │ └── store.py # JsonStore: flock, barrier, atomic replace, ring, ledger
│ ├── services/
│ │ ├── charge_service.py # orchestration: validate, reconcile, mutate
│ │ ├── attachment_service.py # staging -> finalize/rollback
│ │ └── event_bus.py # SSE broker, per-client queue, heartbeat
│ ├── schemas/
│ │ ├── common.py # StrictModel, Envelope, HealthData, error shapes
│ │ ├── charge.py # Charge, Photo, ContestAttachment, HubSnapshot
│ │ ├── booking.py / inspection.py / task.py / event.py
│ │ └── ...
│ ├── api/
│ │ ├── deps.py # AppContext, meta_for, stream_meta_for
│ │ └── v1/{router.py, endpoints/reads.py, commands.py, attachments.py, events.py, dev.py}
│ ├── seed/{bookings,charges,inspections,inventory_reports,notifications,tasks}.json
│ └── static/photos # att_* seed media
├── docs/
│ ├── contract-v1.md # frozen (G-01)
│ ├── openapi-v1.json # frozen snapshot
│ └── contracts/examples/*.json # 15 golden envelopes
├── scripts/{export_fixtures.py, export_openapi.py, verify_fixture_manifest.py, reset_runtime.py}
├── tests/{unit, api, contract}
├── runtime/{state.json, runtime.lock, uploads/, .kxinspect-runtime}
├── pyproject.toml # hatchling, ruff, mypy --strict, pytest+coverage 85%
└── uv.lock / .python-version

Design choices surfaced by the layout:

  • app/domain has no FastAPI/Pydantic/filesystem/clock imports — it is replayable from Dart via exported vectors.
  • JsonStore owns every atomic boundary: commit() is the only writer and os.replace is the only durability primitive.
  • app/core is pure infra: clock abstraction lets every test run against ManualClock without touching the wall clock.

Frontend map

kxinspect_frontend_flutter/
├── lib/
│ ├── main.dart / bootstrap.dart # parse AppConfig, registerDependencies, run KxApp
│ ├── app/
│ │ ├── kx_app.dart
│ │ ├── shell/kx_app_shell.dart # bottom nav + nav rail chrome
│ │ ├── di/{register_dependencies.dart, app_scope_bindings.dart, di_module.dart}
│ │ └── cubit/{booking,connectivity,locale,notifications,sync,theme}
│ ├── core/
│ │ ├── config/app_config.dart # DataSource enum, AppConfig.parse (all errors at once)
│ │ ├── database/{kx_database.dart, local_store.dart, fixture_bundle.dart, domain_mapper.dart}
│ │ ├── network/{kx_api.dart, api_models.dart, fixture_http_client_adapter.dart}
│ │ ├── sync/{sync_service.dart, outbox.dart, live_sync_service.dart, sse_entity_committer.dart}
│ │ ├── time/{anchored_demo_clock.dart, system_clock.dart}
│ │ ├── analytics/*, error/*, storage/*, platform/*
│ │ └── database/attachment_bytes*.dart
│ ├── design_system/
│ │ ├── foundations/{kx_colors,tokens,typography,breakpoints,motion,elevation,radius,spacing}
│ │ ├── theme/kx_theme.dart # light + dark ThemeData
│ │ └── components/{kx_button,banner,card,photo_strip,tabs,image,skeleton, ...}
│ ├── features/
│ │ ├── maintenance/ (hub snapshot, tabs, banners)
│ │ ├── inspection/ (detail page, item navigation)
│ │ ├── charge/ (application/{contest/*, ports}, data, presentation)
│ │ ├── statement/ (unpaid totals, mock pay)
│ │ ├── notifications/ (feed + local notifications)
│ │ ├── settings/ (theme/locale/dev)
│ │ └── analytics_debug/
│ ├── router/{app_router.dart, route_names.dart, route_args.dart, feature_slots.dart}
│ ├── l10n/{app_en.arb, app_cy.arb, generated}
│ └── shared/domain/ids.dart
├── assets/
│ ├── fixtures/{app_state.json, manifest.json, media/, vectors/{charge_state,deadline,namespace}_vectors.json}
│ ├── fonts/{Roboto-*.ttf, Roboto-LICENSE.txt}
│ └── images/
├── test/{unit, widget, golden, helpers, foundation, router, architecture}
├── integration_test/app_test.dart
├── tool/{test_all.sh, android_runtime_proof.sh, aggregate_evidence.dart, check_evidence.dart}
├── docs/{adr, evidence, handoffs, contracts}
└── android/ios/web/macos/linux/windows

What to read first per role:

  • New contributorlib/bootstrap.dartlib/app/di/register_dependencies.dartlib/router/app_router.dart.
  • Feature dev — pick one slice under lib/features/<feature>/{application,data,presentation}; every feature is self-contained, widgets contain no transition/business logic.
  • Design systemlib/design_system/design_system.dart barrel, then foundations/ and components/.

Documentation map

documentation/
├── docs/
│ ├── intro.md
│ ├── guides/{getting-started, project-structure, development-workflow, ci-cd, troubleshooting}.md
│ ├── backend/{overview, architecture, contract-v1, domain-logic, data-models, store-engine,
│ │ api-reference, envelopes-errors, attachments, eventing-sse, configuration, verification}.md
│ ├── frontend/{overview, architecture, bootstrap-di, routing, state-management, design-system,
│ │ data-layer, offline-sync, l10n-theming, testing, features/*.md}
│ └── shared/{contract, fixture-bundle, glossary, decisions}.md
├── docusaurus.config.ts
├── sidebars.ts
└── src/css/custom.css

:::info Convention Backend file references use kxinspect_backend_python/ prefix; frontend uses kxinspect_frontend_flutter/ prefix. Shared artefacts reference both. All code fences are copy-pasteable unless marked # pseudo. :::