Tags

Tags give the ability to mark specific points in history as being important
  • v2.1.2

    protected
    v2.1.2
    
    A weather lens for the week, and themes you can write yourself.
    
    The thermometer button in the toolbar lays an hourly forecast over the
    calendar: a temperature wash per hour, rain bars scaled by amount and faded by
    how likely the rain is, a high and low per day in the header, and DWD
    severe-weather warnings on a row of their own. The calendar recedes underneath
    while the lens is up and comes straight back when it closes. The day view is
    the same component with one column, so it gets the lens too.
    
    Nothing is fetched or drawn until you press the button, and the lens starts
    closed on every load. It is something you reach for, not a mode you leave the
    calendar in, so settings hold only the configuration: a location and a source.
    
    The forecast is fetched by the server rather than the page. The app's own CSP
    is connect-src 'self', so the page could not reach a weather host in any case,
    and this way your coordinates never leave your instance. Operators who would
    rather not depend on a public endpoint can point WEATHER_BRIGHTSKY_URL at their
    own Bright Sky. The data is DWD's, published under CC BY and GeoNutzV, and the
    credit rides on the grid while the lens is up.
    
    Alongside it, two changes to theming. Blacksite is a third built-in theme:
    carbon ground, one red accent, squared corners and monospace type, with
    destructive actions pushed off the accent so Delete still reads as Delete.
    
    And there is now a Custom theme, which is a layer rather than a blank page.
    Pick which built-in theme to start from, override individual colour tokens, and
    add up to 16 KiB of your own CSS on top. It is stored on your account rather
    than the device, so it follows you everywhere you sign in. If a stylesheet ever
    leaves the app unusable, open it with ?safemode=1 to load without it; the
    editor still works, so you can fix the rule or reset.
    
    Android: versionCode 8.
    
  • v2.1.1

    protected
    v2.1.1
    
    The APK no longer carries Google's encrypted dependency-metadata block.
    
    Android's build tools embed that blob into every signed APK by default: the
    app's dependency list, encrypted with a Google public key and readable only by
    Google. This app is not distributed through Google Play, so it was never
    anything but dead weight, and F-Droid refuses an APK that carries one.
    
    Removing it is what lets the official F-Droid build ship this exact signed APK
    instead of a differently signed rebuild. F-Droid builds the app from source on
    its own infrastructure, compares the result against this release byte for byte,
    and distributes this file when the two match. The GitLab release, the project's
    own F-Droid repository and the official F-Droid repository are therefore one
    signing key, and moving between them is an ordinary upgrade rather than an
    uninstall that would take your calendar with it.
    
    No functional changes.
    
  • v2.1.0

    protected
    hypercal 2.1.0
    
    A new name, a from-source build, and a server that is markedly harder to attack.
    
    **`WEBAUTHN_ORIGIN` is now required in production.** A server started with
    `NODE_ENV=production` and no `WEBAUTHN_ORIGIN` refuses to boot. Set it to the
    public origin people reach the instance on, scheme included — e.g.
    `https://calendar.example.com`. It is not a convenience setting: without it a
    passkey assertion is checked against the caller's own `Origin` header, which is
    a check that can only pass. `WEBAUTHN_RP_ID` remains optional and defaults to
    that origin's hostname.
    
    `AUTH_DEV_AUTOLOGIN=1` together with `NODE_ENV=production` is now fatal rather
    than a warning — it treats every session-less request as a seeded admin, which
    is a complete authentication bypass. The Playwright suites run as the new
    `NODE_ENV=e2e`, which is production behaviour in every respect that matters and
    tolerates the bypass the harness needs.
    
    Nothing else needs attention. The schema migrates itself and the Android package
    identifiers are unchanged, so this is an ordinary in-place update.
    
    The name is shorter everywhere a person reads it — launcher, PWA manifest,
    browser tab, F-Droid listing — with a new icon and a refreshed set of
    screenshots. `dev.hypercalendar.app` is untouched, and so is the CalDAV realm
    string: clients cache credentials against (host, realm), so renaming it would
    make every configured device re-prompt for its app password in exchange for a
    name nobody ever sees.
    
    The SQLite engine the on-device backend runs on is now compiled from source
    during the build — emscripten, in CI — instead of arriving as the prebuilt
    `.wasm` inside `@sqlite.org/sqlite-wasm`. F-Droid builds every APK from source
    on their own infrastructure and their scanner rejects a prebuilt binary
    outright, so this is what makes a from-source build possible at all.
    
    Doing it in our pipeline too, rather than only inside the F-Droid recipe, is
    the point: the published APK and the one F-Droid builds now run the same
    engine, and the standalone test suite exercises it on every tag instead of
    leaving it a path only their reviewer discovers is broken.
    
    - **Per-username login throttling.** The existing per-IP limiter cannot help
      with the case that actually matters for a password: many hosts making a few
      attempts each against one account, which stays under every per-IP ceiling
      indefinitely. Failures are now counted against the account itself, wherever
      they come from. It is a throttle and not a lockout — each failure past a
      small free allowance imposes a doubling delay, so knowing a family member's
      username is not a way to lock them out of their own calendar. Failed CalDAV
      Basic auth feeds the same counter.
    - **Origin checking on state-changing `/api` requests.** `SameSite=Lax` cookies
      already stop a cross-site POST, but Lax treats sibling subdomains as
      same-site, so an untrusted neighbour under the same registrable domain was
      not covered. Requests carrying an `Origin` must now match this instance's;
      requests with no `Origin` are unaffected, because they did not come from a
      browser being tricked. `CSRF_ALLOWED_ORIGINS` adds deliberate extras.
    - **Passkey sign-in no longer skips 2FA when it proves only possession.** User
      verification is requested as "preferred", so an authenticator that performs
      none still returns a valid assertion. For an account that has deliberately
      enabled TOTP, that assertion now falls through to the same second step the
      password flow uses.
    - **A real Content-Security-Policy for the SPA shell.** The one inline script —
      the pre-paint theme read — is allowed by a hash computed at startup from the
      file the server is about to serve, rather than by `'unsafe-inline'` or by a
      constant that drifts the next time someone edits the shell.
    - **SSRF hardening** on the outbound fetches behind ICS subscriptions and remote
      CalDAV links, with the same guard shimmed into the on-device backend.
    - **Signing out wipes the device.** The offline event cache, the pending write
      queue, the conflict list and the service worker's cached `/api/events`
      responses are all cleared, so the next account on a shared device starts
      clean.
    - **A leaner, pinned container.** Base images are pinned by digest, and the
      native build toolchain `better-sqlite3` needs is confined to a build stage
      instead of shipping to production. `docker-compose.yml` is now a hardened
      reference deployment — read-only root filesystem, no new privileges.
    
    The security model, security policy, deployment and self-hosting pages have all
    been reworked around the above, including what the optional per-calendar
    encryption does and does not defend against.
    
  • v2.0.3

    protected
  • v2.0.2

    protected
    hyper-calendar 2.0.2
    
    The app now has a name, a face, and a way to talk back.
    
    Android and F-Droid
    
    * The app is called **Hyper-Calendar** everywhere a person reads it — launcher,
      PWA manifest, browser tab and the F-Droid listing. Package identifiers are
      unchanged, so this is an ordinary in-place update.
    * A real launcher icon. Every density shipped Capacitor's scaffolding artwork
      until now, as did all eleven splash screens. The mark is rendered from SVG
      sources in assets/ via 'npm run icons'.
    * Reminder notifications get their own status-bar icon. capacitor.config.ts had
      always named an ic_stat_icon resource that did not exist, so they fell back to
      a generic system glyph.
    
    The F-Droid listing shows images at last
    
    'fdroid update' reads per-app images from fdroid/repo/<applicationId>/<locale>/,
    and nothing ever put them there — so the app page had no screenshots, no banner,
    and only whatever icon could be scraped from the APK. It now carries an icon, a
    feature graphic and four screenshots, generated from the running app by
    'npm run screenshots'.
    
    About and feedback, in the app
    
    * Account menu -> About: version, build, deployment mode, licence and links.
      Until now there was nowhere in the app to read the version the issue tracker
      keeps asking reporters for.
    * Account menu -> Send feedback: describe what happened and it composes a report
      with the version, deployment mode, platform, browser, locale, timezone and
      window size already filled in, then opens a prefilled GitLab issue. Nothing is
      sent by the app — the diagnostics are shown and editable first, and the issue
      is public.
    
    Documentation
    
    The site is the single source of truth: the repository's markdown is now short
    pointers to it, and the site itself finally shows the product.
    
    This is the first release whose APK is built and signed by CI rather than
    uploaded by hand. Getting there took two fixes to that job: it died of SIGPIPE
    after accepting the SDK licences, and then needed a JDK 21 image, which
    Capacitor 8 requires and Debian 12 cannot provide.
    
  • v2.0.1

    protected
    130ef4f2 · Release 2.0.1 ·
    hyper-calendar 2.0.1
    
    Corrected reverse-proxy documentation; APK re-signed with a new release key
    (CN=hyper-calendar). Not upgradeable in place from 2.0.0.
  • v2.0.0

    protected
    hyper-calendar 2.0.0
    
    First published release. Renamed from weekcal.
    Docker image: registry.gitlab.com/kreuz-com-group/hyper-calendar:2.0.0
    APK: dev.hypercalendar.app versionCode 2