Commit Graph
10 Commits
Author SHA1 Message Date
surtic86andClaude Opus 5 e051aa1aec Release 2.2.0
linter / quality (push) Successful in 58s
tests / ci (8.5) (push) Successful in 3m11s
docker / build-and-push (push) Successful in 7m10s
docker / test (8.5) (push) Successful in 3m10s
docker / release (push) Successful in 3s
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 06:13:04 +02:00
surtic86andClaude Opus 5 4530298398 Cut over-engineering found by a repo-wide audit
docker / test (8.5) (push) Successful in 3m10s
linter / quality (push) Successful in 1m5s
tests / ci (8.5) (push) Successful in 3m9s
docker / build-and-push (push) Successful in 21m5s
docker / release (push) Skipped
- Config: auth, services, logging, queue and database only repeated the
  framework's own files and are gone; the others keep only the keys that
  differ (app version, cache serializable_classes, session cookie name,
  Markdown mail theme, the shares disk, three Octane values, Livewire's
  pagination theme and payload guards).
- Email verification is removed: User never implemented MustVerifyEmail,
  so it was never enforced, and SealShare has a single admin and no
  registration. CreateNewUser goes with it.
- FileEncryptionService::encryptFile() and generateSalt() were only used
  by tests; tests build files with encryptTestFile() in tests/Pest.php.
- The expiration options are defined once, as Share::EXPIRATIONS. "30 Days"
  now lasts 30 days instead of a calendar month, and Admin settings only
  save a default expiration that is one of the options.
- One-caller helpers are inlined, the uploader reads chunk responses with
  XHR's responseType, and starter-kit leftovers are removed.
- Docker: PHP reads the PHP_* limits from the environment itself
  (${VAR:-default} in uploads.ini); both entrypoints stop writing the ini.
  docker-compose.yml shares the app and scheduler variables through one
  anchor. The dev image installs gd for the screenshot publisher and fake
  test images.
- Development runs in Docker only: the composer dev script, concurrently,
  laravel/pail, laravel/sail, autoprefixer and the shell-quote override
  are gone.
- phpunit.xml forces the test environment with <server> entries, so tests
  run in the dev container no longer use its real database.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 23:14:33 +02:00
surtic86andClaude Opus 5 026912f98a Run development on the production stack with a Vite dev server
docker-compose.dev.yml extends docker-compose.yml, so development runs the
scheduler too, and takes its settings from .env, which selects the file
through COMPOSE_FILE. The dev image is a stage of the Dockerfile and shares
the production image's PHP extensions; the app listens on port 80 as in
production.

A vite service runs the dev server with hot reload. No ports are published:
OrbStack serves https://app.sealshare.orb.local and
https://vite.sealshare.orb.local, with the ports pinned by label. Without
OrbStack, docker-compose.ports.yml publishes APP_PORT and VITE_PORT on
127.0.0.1. vite.config.js takes the dev server's address from
VITE_DEV_SERVER_URL and listens on IPv4 and IPv6, as OrbStack's proxy
connects over either.

Each start installs Composer packages, clears caches, migrates and links
storage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 22:17:36 +02:00
Andreas Reinhold / reiniandClaude Opus 5 c1906d2009 Stop the SQLite volume from hiding new migrations
Uploads on share.kadenpartner.ch failed with 409 on every chunk after
the update to 2.1. The example docker-compose.yml mounts the SQLite
volume over all of /app/database. Docker fills a volume from the image
only when it is created, so the container kept the 2.0 migrations and
never saw the 2.1 one. share_files.uploaded_chunks was never created,
so the chunk endpoint read null and answered 409. SQLite takes the
unknown "completed_at" in whereNull() as a string, so nothing failed
earlier.

- The image keeps a copy of its migrations in docker/migrations. On
  startup the entrypoint adds the ones missing from database/migrations
  before migrating, so installs with the old mount recover by pulling
  the new image.
- docker-compose.example.yml and docker-compose.yml mount
  sealshare_database at /app/database/sqlite and set DB_DATABASE to the
  file in it. An existing volume can be moved there without losing
  data: its database.sqlite lands at exactly that path.
- Tested with a locally built image: a volume created by 2.0.1 with the
  old mount gets the migration once (not again on restart) and keeps
  its settings; the same volume moved to the new path keeps its data;
  a fresh volume with the new layout starts healthy.
- README and CHANGELOG (Unreleased) describe the new path and how to
  switch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 10:53:27 +02:00
Andreas Reinhold / reiniandClaude Opus 5 40e35bab0e Encrypt uploads in the browser and send them in chunks
A 6 GB upload kept a customer waiting long after its progress bar
reached 100%. The server wrote every upload three times: PHP's
temporary file, Livewire's copy of it ("Processing files...") and the
encrypted file ("Create Share Link"), each a full rewrite of a slow
disk. The unencrypted copy also stayed behind in livewire-tmp.

Now the uploader's browser encrypts each file in 16 MB chunks with
WebCrypto and PUTs them one at a time; the server checks each chunk in
memory and writes it once, already encrypted. Creating the share only
wraps its key and saves the options. A 200 MB upload through the
Docker image took 2.8 s, and its download matched byte for byte.

- SEALCHK2: a 19-byte header (chunk size, 7-byte nonce prefix), then
  ciphertext and tag per chunk. Each nonce holds the chunk index and a
  last-chunk flag (the STREAM construction), so cut or reordered files
  fail to decrypt. SEALCHK1 and the single-block format still read.
- Envelope encryption: one random key per share. With a password it is
  wrapped with Argon2id (sodium, libsodium's interactive limits) in
  shares.wrapped_key, which names its parameters. Password shares from
  before keep their PBKDF2-derived key.
- The upload page registers each selection with FileUploader into a
  pending share of its own, lists the files with their progress, retries
  a failed chunk after 1-16 s, then offers Retry; Remove and Cancel
  abort. UploadChunkController only accepts chunks from the session that
  started the share: a repeat is acknowledged, a skip gets 409 with the
  count stored. Chunks go out as Blobs, which Chromium sends about eight
  times faster than ArrayBuffers.
- Uploads need a secure context: over plain HTTP the page says HTTPS is
  needed and takes no files. The Docker image gains AUTO_HTTPS, which
  serves Let's Encrypt on 443 for SERVER_NAME and redirects 80; without
  it the container stays on HTTP 80 behind a proxy. docker/Caddyfile was
  never loaded and is gone; docker/healthcheck.sh covers both modes.
- "Download all" streams the ZIP with maennchen/zipstream-php (STORE,
  ZIP64) instead of decrypting whole files into memory and writing the
  archive unencrypted to /tmp.
- Pending shares count towards the quota, stay out of the admin
  dashboard and 404 everywhere else. shares:cleanup deletes uploads idle
  for 4 hours and Livewire temporary files older than that.
- PHP's upload limits no longer cap the admin's max file size and
  default to 64M; LIVEWIRE_MAX_UPLOAD_TIME is gone and
  UPLOAD_CHUNK_SIZE_MB is new.
- Tests cover the format, key wrapping, registration limits, the chunk
  endpoint's answers, completing a share, the streamed ZIP, cleanup,
  and in Chromium a real chunked upload and the HTTPS warning; the
  selected-files overflow test runs again. README, website, CHANGELOG
  and .ai/rules follow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 20:49:17 +02:00
Andreas Reinhold / reiniandClaude Opus 5 09e24ade14 Build the amd64 image with QEMU 9.2.2 and only emulate the final stage
docker / test (8.5) (push) Successful in 2m20s
linter / quality (push) Successful in 1m5s
tests / ci (8.5) (push) Successful in 2m16s
docker / build-and-push (push) Successful in 20m13s
docker / release (push) Skipped
QEMU 8.x crashes running x86_64 programs on an arm64 host (QEMU issue
2168), which the 8.1.5 pin walked into, and 10.2 segfaults on the runner
as well; 9.2.2 runs node, composer and install-php-extensions on the
runner's host. The Composer and npm stages now build on the build
machine's platform: their output is the same for every target, so a
multi-arch build runs them once and natively.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
2026-09-13 15:52:58 +02:00
Andreas Reinhold / reiniandClaude Opus 5 d860a16551 Move SealShare from GitHub to Gitea only
docker / test (8.5) (push) Successful in 2m13s
linter / quality (push) Successful in 1m8s
tests / ci (8.5) (push) Successful in 2m7s
docker / build-and-push (push) Failing after 9m54s
docker / release (push) Has been skipped
The workflows live in .gitea/workflows. The Docker workflow logs in to
the Gitea container registry with REGISTRY_TOKEN (Gitea's job token cannot
publish packages yet), publishes gitea.nonameweb.ch/nonameweb/sealshare
with a registry build cache, and makes the release on Gitea with the
version's section of the changelog as its notes.

The README, the website's quick start, both compose files and the image
label point to Gitea; the changelog announces the new image name and
links Gitea. GiteaOnlyTest keeps GitHub and ghcr.io out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
2026-09-13 13:59:07 +02:00
Andreas Reinhold / reiniandClaude Opus 5 c4a17b65c8 Move SealShare onto Livewire Material
Replaces maryUI and daisyUI with nonameweb/livewire-material: the Vibrant
indigo scheme, a system/light/dark theme under sealshare-theme, one top
app bar with the account menu, the upload drop zone and link-ready
moments, M3 fields, dialogs instead of wire:confirm, snackbars instead of
flashed messages, a sortable admin table, and the starter-kit cleanup.
Docker builds assets after Composer; CI drops the Flux step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
2026-09-13 10:49:38 +02:00
surtic86andClaude Opus 4.6 a6f604078b Fix Docker build: add ext-zip, clean cache, fix DB_DATABASE default
- Add php zip extension to Dockerfile (required by ZipArchive)
- Remove bootstrap/cache/*.php during build to prevent stale
  dev-only service providers (e.g. BoostServiceProvider) from loading
- Default DB_DATABASE to /app/database/database.sqlite in
  docker-compose.yml so env() fallback works correctly

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:34:16 +01:00
surtic86andClaude Opus 4.6 e37b322dde Add SealShare file sharing application with encryption, branding, auth, Docker, and Octane support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 11:43:20 +01:00