Skip to content

1.0.0rc2

This second release candidate of 1.0.0 moves all additions to the API to camelCase, also where they are stored, so it needs a fresh database: data is not kept, and there is no migration. It lets users import a service's values from its service info and keep them in sync, tells users and admins what needs attention, and lists the invalid fields of rejected requests where they are known. It also moves the roles of users to a path of their own, so that they can't collide with those of groups, adds labels to invitations and keeps expired invitations for a set time. It is a prerelease, for testing the release before 1.0.0. The registry and cloud-registry-ui ship together: use version 1.0.0-rc2 of the UI with this version. Read the upgrade steps first. See the documentation for details.

Breaking changes

  • Fresh database: stored fields and indexes move to camelCase, without a migration, from any earlier version. The app refuses to start on data or indexes of earlier versions, naming the collections, and no longer adds keys or creators to stored services or warns of data of earlier versions on startup (#352, #353)
  • API: all fields and query parameters that the registry adds move to camelCase, without aliases, so clients must follow (e.g., registrationRules, verifiedAt, serviceId, userId, createdBy, ?includeAccepted=true). The upgrade steps list them all (#352, #353)
  • API: with FOCA 0.21's stricter request checks, query parameters that an operation doesn't declare return 400 Bad Request on all operations (e.g., GET /services, which ignored them), and so do createdAt and updatedAt that aren't date-times, for all users. Responses are checked too, so stored date-time and uri values must be valid: the app logs an error on startup naming services with invalid ones (#368, #369)
  • Access control: new policy rules for imports, syncs and notifications (import-service-info, owners-sync-services, maintainers-sync-services, get-service-sync, list-syncs, list-notifications, dismiss-notifications), which overlays that give policies as a list must include. The registry now needs outgoing connections to fetch service info (#359, #362; #360, #363; #361, #364)
  • Helm chart: on foca-common 0.4.0, which checks audiences, the chart no longer accepts an invalid global config.security.auth.audience if each issuer has its own, which it used to ignore (#350, #351)
  • API: PUT and DELETE /services/{serviceId}/permissions/{userId} move to /services/{serviceId}/permissions/users/{userId}, without an alias: the former paths return 404 Not Found, so move API clients in the same upgrade. With identifiers that start with users/, the former path is the new path of the user without that prefix, so stop clients that weren't moved first (#336, #337)
  • API: service URLs (url) with leading or trailing spaces return 400 Bad Request, as links already did, also when verifying a service: they were stored as written, and would have failed lists of services once responses are validated (#356, #357)
  • Access control: the rule owners-change-permissions moves to .../permissions/users/*, and no longer covers the roles of groups. Overlays that redefine it, or give policies as a list, must move it. Setting owners-change-group-permissions to null now stops owners from changing roles of groups (#336, #337)
  • Invitations: GET /services/{serviceId}/invitations no longer lists accepted invitations unless asked (?includeAccepted=true), now lists expired ones, and all invitations have a status (open, expired or accepted). Clients that show all listed invitations as open must check it (#332, #335)
  • Startup: the app refuses to start if the environment of its service info (service_info.service.environment) isn't one of the values allowed for services (custom.endpoints.services.environments). The defaults pass; check deployments that changed either (#346, #348)
  • API: 400 Bad Request responses to requests with invalid fields list all of them in errors, each with a JSON Pointer or parameter name, a stable code and a message that doesn't quote the value, also for the registry's own checks (URLs, schemes, environments, types, identifiers), with FOCA's problem type and code invalid-request. For those checks, detail now names the locations and messages of all invalid fields instead of describing the first one. Clients that show detail should show the messages of errors at their fields (#317, #378)

Features

  • Import of service info: POST /services/import fetches the service info of a service from a public address, and returns the values for a registration, with safeguards against server-side request forgery (custom.endpoints.services.service_info). The Helm chart has an optional egress NetworkPolicy (egressNetworkPolicy) (#358, #359, #362)
  • Sync of services with their service info: PUT /services/{serviceId}/sync turns it on, by default every 24 hours, without a task queue; while it is on, URLs can't change. GET /syncs and GET /services/{serviceId}/sync show the label (synced, out-of-sync), with a reason from a fixed set. Verified and synced doesn't mean trusted (#360, #363)
  • Sync: ?onlyIfEnabled=true syncs a service only if sync is on for it, and browser apps on other origins can read Retry-After (#365, #366, #367)
  • Notifications: GET /notifications tells users what needs attention on the services they have a role on, and admins also about pending approvals and what the configuration no longer allows, computed from the stored data. Dismissing one with DELETE /notifications/{notificationId} counts for all owners, or all admins (#361, #364)
  • Invitations: an optional label says what an invitation is for (e.g., who it was sent to), returned to those who can list the invitations (#331, #334)
  • Invitations: those that weren't accepted are kept after they expire, so that owners see who needs a nudge, for custom.access_control.invitations.keep_expired_days days (default: 30, at most 365; 0 removes them when they expire, as before), and owners can remove them earlier (#332, #335)
  • Admins can list the registry among its own services, or remove it (/service-info/listing): the entry and its service type are built from the service info and the public URL, it has no owner, doesn't count for service limits, is verified, and is brought up to date when the app starts (#347, #349)
  • Access control: users called groups, or whose identifiers start with groups/, can be granted roles and accept invitations, and the namespaces of issuers may start with groups/ (#336, #337)

Security

  • Image: no pip, from FOCA 0.20, so scans no longer report the packages it vendors, and .trivyignore.yaml has no entries (#350, #351)
  • Logs: rejected request values are no longer logged at INFO (FOCA 0.22), and serviceInfoUrl is checked by the app only, so that FOCA doesn't return or log rejected addresses (#368, #369; #381, #382)
  • Invitations: revoking a user's roles on a service also deletes the invitations to it that the user created and nobody accepted, with the creator's identifier and times, so that a removed user's links stop working. Accepted ones keep them until they expire (#354, #355)
  • Privacy: kept invitations hold their labels, which may name people, and who created them and when, for up to 37 days after they were created by default (7 before): check the default against your privacy statement (#332, #335; #338, #342)
  • Image: the build context excludes more files that can hold secrets (#329, #330)

Fixes

  • python -m cloud_registry.namespace_subjects --dry-run leaves the database as it is: it no longer sets up the app, which changed indexes and configured rules and could keep pods of an older version from restarting. It only counts what is stored, and doesn't check the config as startup does (#339, #343)
  • Sync: custom.endpoints.services.service_info.sync_interval_hours must be from 1 to 8760 hours, or the app refuses to start: larger values failed every worker at startup, and smaller ones fetched from services far more often than needed (#389, #396)

Documentation

  • Upgrade steps: they add up across versions; the matching version of the UI; access control: what kept invitations store, and which identifiers can't accept invitations (#338, #342)
  • API style: additions follow the style of the spec they extend, and additions to spec objects are kept to a minimum and grouped (#352, #353)
  • pyproject.toml: the comment on the FOCA requirement says that FOCA is bumped by hand (#372, #373)
  • Configuration: how many type versions syncs can leave behind without counting for max_unused_service_types; chart README: the new policy rules that values files with list-form policies must add (#389, #396)

Maintenance

  • FOCA 0.22.0, whose base image drops the zlib1g findings of the 0.21.0 one. Validation errors keep the validator's reason as detail and list the invalid fields, where known, in errors; logs name routes instead of paths and no longer quote rejected values at INFO (see Upgrading) (#381, #382)
  • FOCA 0.21.0, pinned with its base image by digest (#368, #369)
  • FOCA 0.20.0 and the library chart foca-common 0.4.0, with new values for the app's probes; the image installs with uv, without pip in it. Images derived from the app's image must use uv too (#350, #351)
  • The check of invalid tokens reads the challenge from the headers of FOCA's exception, ready for later FOCA versions (#370, #371)
  • Tests: the smoke test checks the moved path on the built image (#340, #344)
  • Tests: the configuration is read with foca.get_config() instead of FOCA's deprecated accessor (#374, #375)
  • CI: the release workflow checks the tag and its commit before it runs any script of the tagged commit (#376, #377)
  • CI: Dependabot labels its pull requests type: dependencies (#379, #380)
  • Dependencies: mypy 2.4.1 (#322); uv 0.13.7, also in the image (#383, #386); ruff 0.17.4 and semgrep 1.184.0 in pre-commit (#384); docker/login-action 4.8.0 and sigstore/cosign-installer 4.1.3 (#385); ast-grep 0.51.1, coverage 7.17.2 and types-PyYAML (#386)