Commit Graph

99 Commits

Author SHA1 Message Date
Oleksandr Bezdieniezhnykh 491993f9c1 [AZ-536] [AZ-537] [AZ-538] Argon2id, login rate limit + lockout, CORS https-only
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
AZ-536 — replace unsalted SHA-384 password hashing with Argon2id (RFC 9106).
Stored as PHC string with 64 MiB / 3 iter / 1 lane defaults; legacy SHA-384
hashes detected by prefix and lazily re-hashed on next successful login.
Verify uses CryptographicOperations.FixedTimeEquals on both formats.

AZ-537 — add per-IP sliding window rate limit on /login (ASP.NET Core
RateLimiter, 10/60s default — production-tight) plus DB-backed per-account
limit (5/300s) and consecutive-failure lockout (10 / 15 min) on the users
row. Adds a generic audit_events table with INSERT/SELECT-only grants for
the app role so the per-account count is queryable and admins cannot erase
their own forensic trail. BusinessExceptionHandler maps AccountLocked to
423 and LoginRateLimited to 429, both with Retry-After.

AZ-538 — drop the http://admin.azaion.com origin from CORS, gate
UseHsts() + UseHttpsRedirection() to non-Development envs (1y / preload).

Test infra: Npgsql in the e2e project + a DbHelper for direct DB
inspection used by the AZ-536/537 ACs. appsettings.Development.json
raises PerIpPermitLimit to 1000 so the suite (~270 logins from one
container IP) doesn't false-trip the limiter.

Tests: 53 pass + 3 documented skips (per-IP rate limit needs distinct
client IPs; HSTS/HTTPS redirect need ASPNETCORE_ENVIRONMENT=Production).

Code review: PASS_WITH_WARNINGS — 0 Critical, 0 High, 1 Medium, 3 Low.
See _docs/03_implementation/reviews/batch_01_cycle2_review.md.

Closes AZ-530 epic batch 1 of 4.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 04:52:31 +03:00
Oleksandr Bezdieniezhnykh 9679b5636f chore(autodev): advance state to Step 10 (Implement) for cycle 2
Reconciliation: prior session completed Step 9 (New Task) which
produced AZ-531..AZ-538 in _docs/02_tasks/todo/ and refreshed the
_dependencies_table.md, but did not bump _autodev_state.md. Folder
state is authoritative per state.md rule #4; advancing the pointer.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 04:20:32 +03:00
Oleksandr Bezdieniezhnykh 3a925b9b0f refactor: remove obsolete resource download and installer endpoints
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
- Deleted the `POST /resources/get/{dataFolder?}` and `GET /resources/get-installer` endpoints as part of the architectural shift towards simplified resource management.
- Removed associated methods and configurations, including `ResourcesService.GetEncryptedResource`, `ResourcesService.GetInstaller`, and related properties in `ResourcesConfig`.
- Cleaned up environment variables and configuration files to reflect the removal of installer-related settings.
- Eliminated the `GetResourceRequest` DTO and its validator, along with the `WrongResourceName` error code.
- Updated documentation to clarify the changes in resource handling and the retirement of per-user file encryption.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 04:17:55 +03:00
Oleksandr Bezdieniezhnykh c7b297de83 refactor: remove deploy.cmd and update Dockerfile for health checks
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
- Deleted the deploy.cmd script as it was no longer needed.
- Updated Dockerfile to include curl for health checks and added a non-root user for improved security.
- Modified health check command to use curl for better reliability.
- Adjusted docker-compose.test.yml to reflect changes in health check configuration.
- Cleaned up appsettings.json and removed unused configuration properties.
- Removed Resource entity and related requests from the codebase as part of the architectural shift.
- Updated documentation to reflect the removal of hardware binding and related endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 08:47:21 +03:00
Oleksandr Bezdieniezhnykh 43fe38e67d fix(test-infra): reset docker volumes before each test run
The test-db postgres image only executes /docker-entrypoint-initdb.d on a
fresh data directory. Reusing the volume from a prior run silently skipped
new schema migrations (e.g. 04_detection_classes.sql, 05_resources.sql),
producing phantom "relation does not exist" failures on the second and
subsequent runs. Always start with a clean state.

Verified: two consecutive runs both green (48/48 e2e).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:57:18 +03:00
Oleksandr Bezdieniezhnykh 0c9340a1af chore(autodev): mark cycle 1 Implement step complete
All four cycle-1 tasks (AZ-513, AZ-196, AZ-183, AZ-197) are In Testing on
Jira. Full suite passes (48/48 e2e + 2/2 unit) after a fresh test-DB volume.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:54:02 +03:00
Oleksandr Bezdieniezhnykh 4914f08aff [AZ-197] Loosen Hardware_endpoints_are_removed test for /resources/check
POST /resources/check now collides with the multipart-only file-upload
route POST /resources/{dataFolder?} (with dataFolder="check"). A JSON POST
to that path therefore returns 415 (UnsupportedMediaType) instead of 404.
Both signal that the deleted hardware-binding endpoint is gone — what
matters for AC-2 is that no hardware-binding side-effect runs. Test now
accepts either status for /resources/check; PUT /users/hardware/set
remains a strict 404.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:53:26 +03:00
Oleksandr Bezdieniezhnykh 5e90512987 [AZ-197] Remove hardware ID binding from resource flow
Sealed-Jetson + SaaS architecture eliminates the credential-reuse-across-
machines threat that motivated hardware fingerprint binding. The binding's
only remaining effect was a real production failure mode on legitimate
hardware events.

Production:
- Drop PUT /users/hardware/set and POST /resources/check.
- Simplify POST /resources/get/{dataFolder?} (no Hardware field).
- Remove CheckHardwareHash, UpdateHardware, Security.GetHWHash.
- GetApiEncryptionKey signature: (email, password) — no hardwareHash.
- Drop SetHWRequest DTO and Hardware property from GetResourceRequest.
- Remove HardwareIdMismatch (40) and BadHardware (45) ExceptionEnum
  entries; numeric codes left as a gap, not for reuse.

Wire-compat policy: drop entirely (no Loader; no in-flight legacy
clients). Stale callers will see 404s, which is the right loud failure.

Tombstones:
- User.Hardware DB column kept (nullable, unused) — separate cleanup
  ticket for the migration per workspace "no rename without confirmation".
- User.LastLogin is now never written by app code (only writer was inside
  the deleted CheckHardwareHash); flagged in batch_06_review for a future
  ticket.

Tests:
- Delete e2e HardwareBindingTests (165 lines) and Azaion.Test
  UserServiceTest (sole test was CheckHardwareHashTest).
- Drop Hardware payloads + /resources/check preconditions from e2e
  ResourceTests, SecurityTests, ResilienceTests; drop hardwareId arg
  from Azaion.Test SecurityTest.
- Add SecurityTests.Hardware_endpoints_are_removed_AZ_197 (AC-2 regression
  asserting both removed routes return 404).

Docs:
- architecture.md: System Context note, ADR-003 new key formula, ADR-004
  retired with rationale.
- diagrams/flows/flow_hardware_check.md: tombstoned.

Also archives the four batch-1+batch-2 task files into _docs/02_tasks/done/
(file moves were missed by the batch_05 commit).

Code review: PASS — see _docs/03_implementation/reviews/batch_06_review.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:46:39 +03:00
Oleksandr Bezdieniezhnykh 5ca9ccab2c [AZ-513] [AZ-196] [AZ-183] Add /classes CRUD, /devices, fleet OTA
AZ-513: POST/PATCH/DELETE /classes for detection-class CRUD; new
DetectionClass entity, schema, DTOs, IDetectionClassService. Unblocks
ui/AZ-512.

AZ-196: POST /devices auto-assigns sequential azj-NNNN serial+email
+password and inserts a CompanionPC user. Returns plaintext credentials
for the provisioning script.

AZ-183: Resources table + POST /get-update + POST /resources/publish
for fleet OTA. Per-resource encryption_key column AES-256-CBC encrypted
at rest with ResourcesConfig.EncryptionMasterKey; ICache wraps the
per-(arch,stage) latest-versions lookup and is invalidated on publish.

Adds IDbFactory.RunAdmin<T> overload for write-and-return.

Backfills _docs/02_document/module-layout.md to satisfy the implement
skill's File Ownership prerequisite (the _docs/ artifact set predates
the Step 1.5 module-layout addition).

Code review: PASS_WITH_WARNINGS — see
_docs/03_implementation/reviews/batch_05_review.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:34:42 +03:00
Oleksandr Bezdieniezhnykh f13c57b314 chore: migrate autodev state file to current format
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:00:58 +03:00
Oleksandr Bezdieniezhnykh e40ea3eeaa [AZ-513] Add task spec: /classes CRUD routes (POST + PATCH + DELETE)
Cross-workspace prerequisite filed by ui/ autodev cycle 3 batch 15
BLOCKING gate. The ui/ workspace's AdminPage.tsx already calls
POST /classes and DELETE /classes/{id} today (broken end-to-end against
this service - pre-existing bug); ui/ AZ-512 needs PATCH /classes/{id}
for the in-place edit affordance promised by Architecture Vision P12.

Spec covers:
- POST /classes  - creates a detection class
- PATCH /classes/{id}  - partial-merge update
- DELETE /classes/{id}  - removes a class
- All three guarded by apiAdminPolicy (matches /users precedent)
- IDetectionClassService + DetectionClassService in Azaion.Services
- DTOs in Azaion.Common/Requests
- 10 ACs covering happy + auth + 404 paths

Tracker: AZ-513 (Jira project AZ, parent epic AZ-509, Blocks AZ-512).
Cross-workspace context: ui/_docs/_process_leftovers/2026-05-13_az-512-admin-classes-prereq.md
Complexity: 3 points.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 03:58:45 +03:00
Oleksandr Bezdieniezhnykh 15631b37cb chore: sync .cursor from suite
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
2026-05-09 05:18:07 +03:00
Oleksandr Bezdieniezhnykh 64887e5bfc chore: sync .cursor from suite
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
2026-05-05 01:08:45 +03:00
Oleksandr Bezdieniezhnykh 7ba2f1b9c2 chore: sync .cursor skills from suite
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
2026-05-03 17:43:23 +03:00
Oleksandr Bezdieniezhnykh ea55f695dc chore: sync .cursor skills from suite
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
2026-04-29 17:03:55 +03:00
Oleksandr Bezdieniezhnykh 210b249665 chore: sync .cursor from suite
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
Made-with: Cursor
2026-04-25 19:44:45 +03:00
Oleksandr Bezdieniezhnykh ad8c690550 Remove obsolete build-arm.yml configuration file from Woodpecker pipeline. This file is no longer needed following recent updates to the build process.
ci/woodpecker/push/01-test Pipeline failed
ci/woodpecker/push/02-build-push unknown status
2026-04-25 06:53:15 +03:00
Oleksandr Bezdieniezhnykh 77eced4550 [AZ-206] Update Woodpecker build configuration for Docker login
ci/woodpecker/manual/build-arm Pipeline was successful
Replaced HARBOR_USER and HARBOR_TOKEN with REGISTRY_USER and REGISTRY_TOKEN in the build-arm.yml file. Adjusted the docker login command and updated the image tag format to include 'azaion' in the registry path for consistency with the new registry structure.
2026-04-21 20:39:08 +03:00
Oleksandr Bezdieniezhnykh 3f4696a046 [AZ-205] Authenticate to Harbor before pushing build images
Add HARBOR_USER/HARBOR_TOKEN from Woodpecker secrets and a docker login
step before the existing build/push, so pipelines can push to the new
TLS-authenticated Harbor registry.
2026-04-20 04:10:42 +03:00
Oleksandr Bezdieniezhnykh d5255da0fe [AZ-204] OCI revision labels + AZAION_REVISION env
Made-with: Cursor
2026-04-20 03:58:46 +03:00
Oleksandr Bezdieniezhnykh 4ae74adcb5 [AZ-203] Parameterize registry host via REGISTRY_HOST secret
Pipeline reads $REGISTRY_HOST from the Woodpecker global secret
'registry_host' instead of hardcoding 'localhost:5000'. The full
host:port lives in the secret, so Harbor migration (AZ-205) becomes
one secret edit rather than editing every submodule pipeline.

Made-with: Cursor
2026-04-20 03:49:20 +03:00
Oleksandr Bezdieniezhnykh 34eba48b45 Sync .cursor from suite (autodev orchestrator + monorepo skills) 2026-04-18 22:03:43 +03:00
Oleksandr Bezdieniezhnykh e94842d330 [AZ-189] Update coding and testing rules for clarity and consistency
- Revised coding standards to emphasize readability, meaningful comments, and test verification.
- Adjusted test coverage thresholds to 75% for business logic and clarified expectations for test scenarios.
- Enhanced guidelines for handling skipped tests, emphasizing the need for investigation and resolution.
- Updated commit message format and length requirements for better adherence to Git conventions.

Made-with: Cursor
2026-04-17 20:27:28 +03:00
Oleksandr Bezdieniezhnykh d7f2b75fe1 [AZ-189] Show only test runner output
Made-with: Cursor
2026-04-16 07:12:16 +03:00
Oleksandr Bezdieniezhnykh 5c19c27153 [AZ-189] Show test names in output
Made-with: Cursor
2026-04-16 07:10:11 +03:00
Oleksandr Bezdieniezhnykh 83097aef68 [AZ-189] Silence db/api container logs
Made-with: Cursor
2026-04-16 07:09:34 +03:00
Oleksandr Bezdieniezhnykh 63a26ac628 [AZ-189] Simplify run-tests.sh
Made-with: Cursor
2026-04-16 07:04:13 +03:00
Oleksandr Bezdieniezhnykh 3d665032e6 [AZ-189] Reduce test output noise
Made-with: Cursor
2026-04-16 07:02:58 +03:00
Oleksandr Bezdieniezhnykh c6b2beb833 [AZ-195] Remove unrunnable test
Made-with: Cursor
2026-04-16 07:00:50 +03:00
Oleksandr Bezdieniezhnykh 74f5594b0c [AZ-200] Drop email length rule
Made-with: Cursor
2026-04-16 06:59:12 +03:00
Oleksandr Bezdieniezhnykh 88c7b288df [AZ-199] [AZ-200] [AZ-201] [AZ-202] Fix API bugs
Made-with: Cursor
2026-04-16 06:55:11 +03:00
Oleksandr Bezdieniezhnykh 5286b6b8e3 [AZ-198] Block disabled user login
Made-with: Cursor
2026-04-16 06:49:00 +03:00
Oleksandr Bezdieniezhnykh 9da34a594b [AZ-189] Fix e2e test run
Made-with: Cursor
2026-04-16 06:45:38 +03:00
Oleksandr Bezdieniezhnykh d320d6dd59 [AZ-189] [AZ-190] [AZ-191] [AZ-192] [AZ-193] [AZ-194] [AZ-195] Add e2e blackbox test suite
Made-with: Cursor
2026-04-16 06:25:36 +03:00
Oleksandr Bezdieniezhnykh 1b38e888e1 Allow manual CI builds
ci/woodpecker/manual/build-arm Pipeline failed
Made-with: Cursor
2026-04-12 05:41:32 +03:00
Oleksandr Bezdieniezhnykh 4f4c6b1f6f Add push event trigger to Woodpecker CI configuration 2026-04-12 05:10:56 +03:00
Oleksandr Bezdieniezhnykh 359bab3c92 Sync .cursor from detections 2026-04-12 05:05:08 +03:00
Oleksandr Bezdieniezhnykh 884abf7006 CI: main tag without prefix
Made-with: Cursor
2026-04-12 04:12:01 +03:00
Oleksandr Bezdieniezhnykh 38344d8c62 update woodpecker add dev branch
Made-with: Cursor
2026-04-11 20:40:28 +03:00
Oleksandr Bezdieniezhnykh 5bb566876f Switch to Woodpecker CI
Made-with: Cursor
2026-04-10 01:28:51 +03:00
Oleksandr Bezdieniezhnykh 98a80cf942 Comment out amd64 matrix
Made-with: Cursor
2026-04-09 23:33:22 +03:00
Oleksandr Bezdieniezhnykh 34a7a0bdf9 Remove Woodpecker CI configuration file as multi-platform support is no longer needed. 2026-04-09 19:17:41 +03:00
Oleksandr Bezdieniezhnykh 0f01e5a7c7 Add multi-platform support in Woodpecker CI configuration
Introduced a matrix for building on both linux/arm64 and linux/amd64 platforms. Updated the tagging format to include platform-specific tags for better image management.
2026-04-09 13:28:45 +03:00
Oleksandr Bezdieniezhnykh e1a93135c1 Refactor authentication logic to improve security and streamline user role management 2026-04-08 06:32:45 +03:00
Oleksandr Bezdieniezhnykh 04a18804c5 Update .gitignore to exclude log files and directories 2026-04-06 07:06:54 +03:00
Oleksandr Bezdieniezhnykh b970b2f593 Update Dockerfile for multi-platform support and enhance nginx registry script with volume and environment variable configurations 2026-04-06 04:59:49 +03:00
Oleksandr Bezdieniezhnykh ce44d565c8 rename Azaion.Api -> Azaion.AdminApi 2026-03-25 17:57:27 +02:00
Oleksandr Bezdieniezhnykh 61f7c36198 add .net launch json configs
Made-with: Cursor
2026-03-25 17:52:39 +02:00
Oleksandr Bezdieniezhnykh d96971b050 Update .gitignore to include .env and .DS_Store files
Add .cursor autodevelopment system
2026-03-25 17:41:10 +02:00
Oleksandr Bezdieniezhnykh 44e75afc4f Update project to .NET 10.0 and upgrade dependencies in Dockerfile and project files 2026-03-09 22:27:48 +02:00