Edit README with battalion information - #4
MateuszKosowski wants to merge 69 commits into
Conversation
Initial configuration for microservices and Docker setup
Add JaCoCo coverage reporting and SonarQube integration. Closes #4
* Add GitHub Actions CI for tests * Fix Gradle wrapper permissions in CI
) * Add JWT secret key and Eureka URL to environment example * Add PostgreSQL configuration to Docker and update environment variables * Add PostgreSQL and JWT dependencies, update Docker environment variables, and create users table * Add health checks and service dependencies to Docker Compose configuration * Implement authentication with JWT: add AuthController, JwtService, and user login functionality * Add token validation and authentication error handling: implement validateToken method, add custom exceptions for bad credentials and email not found * Add JWT authentication and security configuration: implement JwtFilter, SecurityConfig, and AuthClient; update application structure for watermark service * Refactor JWT filter and security configuration: improve error handling in JwtFilter and update permitted endpoints in SecurityConfig * Add PostgreSQL integration for tests: configure Testcontainers for PostgreSQL in ApplicationTests and update build.gradle.kts for test dependencies
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| - | - | Generic Password | 243510f | .env.example | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
* Rebase onto main * fix: disable Eureka/Config discovery in tests for CI compatibility * Clean up * Move .yaml properties to config-server + WATERMARK_APP_KEY * Preserve RGB colors in watermark embedding Update steganography to preserve original RGB colors when writing updated luminance. WatermarkImageData now stores an rgb matrix and withUpdatedLuminance builds a TYPE_INT_RGB image, using a new colorWithLuminance routine that adjusts RGB channels to match the target luminance. Removed unused WritableRaster import. Tests updated to set a test watermark app-key and disable MVC filters, and to assert embedded image dimensions and that color pixels are preserved (added containsColorPixels helper). * Instead of manual ownerId we retrieve data from JWT * Rename ownerId to ownerIdentity in watermark embedding and extraction processes * fix: preserve original colors when embedding watermark * fix: read pixels via getRGB and lower DELTA to 50 Raster band order depends on BufferedImage type (BGR for many PNGs), which swapped R/B channels. getRGB returns ARGB regardless. Lowering DELTA reduces blockiness in flat regions while keeping JPEG q>=0.5. * fix: bump DELTA to 70 for CI JPEG robustness Linux JDK JPEG encoder is more aggressive than Windows; DELTA=50 made the q>=0.7 round-trip pass locally but fail on CI. 70 keeps headroom on CI while still reducing blockiness vs the original 80. --------- Co-authored-by: Mateusz Kosowski <mateuszkosowski03@gmail.com>
* feat: add ai-service for image classification (closes #15) Introduces a new ai-service microservice that classifies uploaded images and returns ImageNet labels mapped to broad categories. Integrates it with watermark-service via a Feign client so the watermark endpoint enriches responses with classification metadata in headers. - ai-service: Spring Boot module with ClassificationController/Service and CategoryMapper - watermark-service: AiServiceFeignClient + ClassificationResult DTO, controller now exposes POST /api/watermark with multipart upload - docker-compose: ai-service container wiring - settings.gradle.kts: register ai-service module * test: mock AiServiceFeignClient in watermark-service integration tests * Address PR feedback for ai-service - WatermarkController: catch ai-service failures and fall back to 'unknown' classification headers so embed still succeeds when AI is down. Restore method-level Javadocs that were dropped during the earlier refactor. - CategoryMapper: switch from Map.ofEntries (unspecified iteration order) to an ordered List<Map.Entry> so category resolution stays deterministic if overlapping keywords are ever added. - AiServiceApplicationTests: replace deprecated @MockBean with @MockitoBean (matches the convention already used in watermark-service tests). - Add ClassificationServiceTest: real smoke test that loads MobileNetV2 ONNX and classifies a small Samoyed image, asserting top-1 maps to the 'dog' category. Bundles the ~14MB ONNX model, ImageNet synset, and test image under src/test/resources/model so the test is fully hermetic and runs in CI in <1s after model load. * fix: resolve CI failure by avoiding double-reading MultipartFile and hardening model loading * feat: add security to ai-service and fix config loading * style: align ai-service with project-wide practices (exception handling) * refactor: migrate ai-service config to config-server and enable native search --------- Co-authored-by: Jakub Rusek <jakub.rusek.01@gmail.com>
* feat: integrate SvelteKit GUI with AI classification and dockerize Brings the frontend from add-initial-frontend onto current main (which extracted ai-service into its own microservice) and wires it end to end. - add gui/ (SvelteKit) and a gui service to docker-compose on :5173 - switch adapter-auto -> adapter-static (SPA) served by nginx - nginx reverse-proxies /api and /auth to the backend so the browser uses same-origin relative paths; removes the need for CORS - display the detected image class read from the X-Image-* headers that watermark-service returns from /embed - vite dev proxy mirrors the nginx routing for `npm run dev` Lockfile is intentionally not committed; the Docker build uses npm install. * fix: forward JWT from watermark-service to ai-service classify * feat: add detect, extract and visualize tabs to GUI * fix: friendly notice when extracting from image without watermark
…tiers
Brings the Python watermark-service to parity with the Java implementation
and closes the security regressions left by the original port.
Spring Cloud Config Server integration
Startup polls config-server (application + watermark-service profiles),
flattens propertySources, merges into pydantic Settings with env-var
precedence. Retries with exponential backoff (1s → 16s) per path and
keeps whatever properties resolved if one path stays unreachable.
Placeholder resolver (${VAR:default}) is bounded to 16 passes so cyclic
references can't hang startup.
AES-256-GCM payload encryption
Watermark payload (owner|text) is sealed with AES-GCM keyed off
WATERMARK_APP_KEY (SHA-256 derived). Magic bytes WMPY + version byte +
96-bit nonce per embed + 128-bit auth tag. Without the app key nobody
can read or forge a watermark — closes the plaintext-payload spoofing
hole. Service refuses to boot with the public dev default key unless
WATERMARK_DEV_MODE=true is set explicitly.
Reed-Solomon ECC layer
16 parity bytes wrap the encrypted envelope so dwtDctSvd's occasional
bit-flips on threshold-sized images don't fail the GCM auth tag.
Corrects up to 8 byte errors per watermark. Envelope overhead: 49 bytes
(17 header + 16 GCM tag + 16 RS parity).
Adaptive length_bits tiers with embed-time verification
Embed picks the largest watermark capacity an image can carry, verifies
the round-trip end-to-end (catches any decode/decrypt exception, not
just CryptoError), falls back to a smaller tier if ECC can't recover.
Detect tries each known length until one decrypts.
short ≥ 1080 px AND long ≥ 1600 px → 1024 bit, ~71 bytes of text
short ≥ 1024 px AND long ≥ 1024 px → 768 bit, ~39 bytes
Below the smaller tier the image is rejected with a clear 400.
Strict input boundary on /embed
Server-side PNG magic-byte check rejects JPG/WebP up front so the
GUI's "PNG-only" promise is enforced at the API boundary, not just
by the file-picker filter. Image and text payloads are size-capped
(25 MB / 4 KB) to defang form-data DoS. EXIF orientation is applied
during decode so portrait photos pick the right tier.
Auth tightening (closed regressions vs Java)
- JWT required on /detect and /visualize (matches Java SecurityConfig)
- auth-server validation uses strict `body is True` — schema drift
fails closed instead of accepting truthy alternatives
- Principal extracted from JWT is sanitized through an identifier
regex before being embedded; non-matching identifiers fall back to
"User" rather than poison the envelope
- Split connect/read timeouts (2s / 5s) on the validate call
ai-service client made non-blocking
Switched from sync httpx.Client to AsyncClient with split
connect/read/write/pool timeouts so a slow ai-service can't park the
embed handler's event loop. Classification still falls back to
"unknown" on any error.
New POST /api/watermark/capacity
Returns maxTextBytes (renamed from maxTextChars — the budget is UTF-8
bytes, not codepoints) + chosen tier + image dimensions for the
calling principal. Powers the GUI's live byte counter.
Embed-time errors mapped cleanly
embed_text can raise RuntimeError when verification fails at every
tier; routes layer maps it to 422 with the descriptive message
instead of leaking a stack trace.
Eureka registration
Passes health_check_url + status_page_url so the dashboard reflects
real /health state instead of py-eureka-client defaults.
GUI updates (Svelte 5)
- Embed-tab file picker restricts to image/png (clean source = best
ECC margin); other tabs still accept JPG so users can see "this
copy lost the watermark"
- Live capacity probe on image select with AbortController guarding
against stale responses from a previous selection; file-signature
dedup so re-binding the same FileList doesn't re-upload
- Byte counter under the text input; submit disabled when over budget,
image too small, OR capacity probe still in flight
- Subtle PNG-only hints on every tab + explicit "keep as PNG" note
under the download button (subdued slate-500 styling, WCAG AA)
- Field rename: capacity.maxTextChars → capacity.maxTextBytes;
response header X-Max-Text-Chars → X-Max-Text-Bytes
Hardening
- Dockerfile runs uvicorn as non-root user (uid 10001)
- LOG_LEVEL actually configures the root logger
- WATERMARK_DEV_MODE flag wired through docker-compose so the dev
default key boots locally but production deploys must set a real
secret or set DEV_MODE explicitly
- Dropped unused Settings.port + dead PyJWT dependency
- Removed WATERMARK_LENGTH_BITS env (tier selection is automatic)
- Bumped service version to 0.2.0-py
Documentation
README covers config-server integration, crypto design, adaptive tier
math (with corrected envelope overhead), capacity calculation, and an
explicit "PNG in, PNG out, do not recompress" user contract explaining
why the watermark dies on JPG re-encode (DWT-DCT-SVD is a fundamental
DCT-frequency algorithm).
Tests: 33 passing (incl. 1024-bit/768-bit tier roundtrips, FHD landscape
and portrait, wrong-key returns not-watermarked, auth required on
detect/visualize, capacity reporting per tier, embed verification with
tier downgrade, async ai-client mocks). Removed the all-xfail JPEG
robustness sweep — the limitation is fundamental to DWT-DCT-SVD and now
documented in README.
Harden watermark-service-py: AES-GCM crypto, config-server, adaptive capacity (closes #23)
…acy-java-watermark chore: remove legacy Java watermark-service and watermark-client (#26)
* feat(registration): implement user registration endpoint with validation and error handling * feat(registration): add user registration form with validation and error handling
Implement issue #30
- Added springdoc-openapi to Java services (ai, auth, subscription) - Added technical descriptions to FastAPI routes in watermark-service - Updated README.md with OpenAPI documentation links - Exposed ai-service port in docker-compose for Swagger access - Configured security to permit access to Swagger UI endpoints
docs: add OpenAPI documentation to all service endpoints
* docs: add OpenAPI and improve test coverage * refactor: inject Clock for testability and centralize springdoc version * fix: provide default values for config-server security credentials * refactor: simplify token reservation response mapping
docs: consolidate OpenAPI definitions from all services and add inter…
Add project linting and code style checks
* Implement paid subscription upgrade lifecycle � Conflicts: � subscription-service/src/main/java/pl/zzpj/subscription_service/application/PaymentApplicationService.java � subscription-service/src/main/java/pl/zzpj/subscription_service/application/SubscriptionQueryService.java � subscription-service/src/main/java/pl/zzpj/subscription_service/application/TokenReservationCommandService.java � subscription-service/src/main/java/pl/zzpj/subscription_service/controller/MockPaymentController.java � subscription-service/src/main/java/pl/zzpj/subscription_service/controller/TokenReservationController.java � subscription-service/src/main/java/pl/zzpj/subscription_service/domain/payment/PaymentProvider.java � subscription-service/src/main/java/pl/zzpj/subscription_service/domain/subscription/ActiveSubscription.java � subscription-service/src/main/java/pl/zzpj/subscription_service/domain/subscription/PlanCode.java � subscription-service/src/main/java/pl/zzpj/subscription_service/domain/token/TokenReservationPolicy.java � subscription-service/src/main/java/pl/zzpj/subscription_service/domain/token/decision/TokenDecision.java � subscription-service/src/main/java/pl/zzpj/subscription_service/infrastructure/payment/MockPaymentProvider.java � subscription-service/src/main/java/pl/zzpj/subscription_service/persistence/SubscriptionStore.java � subscription-service/src/main/java/pl/zzpj/subscription_service/persistence/repository/ActiveSubscriptionRepository.java � subscription-service/src/main/java/pl/zzpj/subscription_service/persistence/repository/PaymentSessionRepository.java � subscription-service/src/test/java/pl/zzpj/subscription_service/application/SubscriptionQueryServiceTest.java � subscription-service/src/test/java/pl/zzpj/subscription_service/application/TokenReservationCommandServiceTest.java * Improve subscription and upload feedback in UI * Document subscription lifecycle and mock payments
Add a source-verified API reference under docs/api/: - README.md: system map, nginx routing, auth model, token economy, demo accounts, error model, and a Known Issues callout - per-service docs: auth-server, subscription-service, ai-service, watermark-service, infrastructure (eureka, config-server, actuator) Rebuild stegocloud-openapi.json (3.1): - real on-service paths with per-path servers (executable in api-docs.html) - add token-reservation endpoints; concrete watermark response schemas (image/png + X-* headers, JSON for detect/extract/capacity) - fix /watermark/health -> /health, register 200 -> 201, typed login response, and add 401/403/409/413/422/500 error responses Wire the new docs into README.md and flag the TokenReservationController wiring defect (missing @RestController/@RequestMapping -> /api/tokens/ reservations returns 404, breaking watermark paid operations).
A merge dropped @RestController and @RequestMapping from TokenReservationController, so /api/tokens/reservations was unmapped and every reservation returned 404. The watermark-service surfaced this as "Could not reserve tokens for this operation" on embed.
…nsive-testing test: comprehensive automated testing strategy (#19)
…tation docs(api): endpoint reference + rebuilt OpenAPI spec
docs: add LaTeX documentation and UML diagrams for StegoCloud
- Render UML diagrams as vector SVG->PDF (sharp at any zoom) with Polish glyphs - Add document purpose section, fix DCT/DWT-DCT-SVD wording, align AI example, add usage flow - Replace raster PNG diagrams with vector PDFs
* docs(readme): enhance project overview and technical details, update quick start and demo accounts * chore(docker): add TESTCONTAINERS_HOST_OVERRIDE for local testing * delete .idea * delete WYMAGANIA.md * docs: update project documentation structure and add README * feat: refactor watermark console components and improve structure
Mission accomplished, General