<feed xmlns='http://www.w3.org/2005/Atom'>
<title>progmaweb, branch feature/progmasoft-credentials</title>
<subtitle>The site and account service of Progmasoft: a Next.js frontend and an ASP.NET Core API.</subtitle>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/'/>
<entry>
<title>Merge branch 'main' into feature/progmasoft-credentials</title>
<updated>2026-10-23T03:36:56+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-23T03:36:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=7f1cb91eb16bc3d7fd78320465c32d5e2f47ec97'/>
<id>7f1cb91eb16bc3d7fd78320465c32d5e2f47ec97</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #42 from Progmasoft/ops/harden-systemd-units</title>
<updated>2026-10-23T03:36:23+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-23T03:36:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=a68bb18e2d750fabcbcff985b5fe921d7c828d7e'/>
<id>a68bb18e2d750fabcbcff985b5fe921d7c828d7e</id>
<content type='text'>
Harden the systemd units of the API and the web frontend</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Harden the systemd units of the API and the web frontend</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'main' into feature/progmasoft-credentials</title>
<updated>2026-10-23T03:08:33+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-23T03:08:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=d8c4fafd30647b0063e3ec52e1c4a95cf61106eb'/>
<id>d8c4fafd30647b0063e3ec52e1c4a95cf61106eb</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'main' into ops/harden-systemd-units</title>
<updated>2026-10-23T03:08:30+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-23T03:08:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=8a2a3ed0bdc109216a75a345407d61deda60fa28'/>
<id>8a2a3ed0bdc109216a75a345407d61deda60fa28</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #44 from Progmasoft/security/next-16.4.2</title>
<updated>2026-10-23T03:07:50+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-23T03:07:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=415e949e6621b3d21dd5fbe7cd66440af14e410d'/>
<id>415e949e6621b3d21dd5fbe7cd66440af14e410d</id>
<content type='text'>
Update Next.js to 16.4.2 for an unauthenticated RCE</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Update Next.js to 16.4.2 for an unauthenticated RCE</pre>
</div>
</content>
</entry>
<entry>
<title>Document every OAuth member and namespace for the API reference</title>
<updated>2026-10-23T03:01:51+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T03:01:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=a8d768876e7cff3e3eeaa6e310149ed7f5894db0'/>
<id>a8d768876e7cff3e3eeaa6e310149ed7f5894db0</id>
<content type='text'>
The documentation check of CI requires a comment on every API item and
a page for every namespace; 38 items of Progmasoft.OAuth had none. The
private handlers and helpers get summaries, MemoryOAuthDatabase its
field, and docs/api/namespaces describes Progmasoft.OAuth and its
Developers, Endpoints, Pages and Storage namespaces.

Verified: dotnet build in Release, dotnet docfx with warnings as
errors, and CheckDocumentation: all 353 API items are documented.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The documentation check of CI requires a comment on every API item and
a page for every namespace; 38 items of Progmasoft.OAuth had none. The
private handlers and helpers get summaries, MemoryOAuthDatabase its
field, and docs/api/namespaces describes Progmasoft.OAuth and its
Developers, Endpoints, Pages and Storage namespaces.

Verified: dotnet build in Release, dotnet docfx with warnings as
errors, and CheckDocumentation: all 353 API items are documented.
</pre>
</div>
</content>
</entry>
<entry>
<title>Update Next.js to 16.4.2 for an unauthenticated RCE</title>
<updated>2026-10-23T02:57:26+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T02:57:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=8e4f376c19a05c3a7ac73576515f4baa62ed206d'/>
<id>8e4f376c19a05c3a7ac73576515f4baa62ed206d</id>
<content type='text'>
pnpm audit reports a critical advisory for next &gt;=16.0.0 &lt;=16.4.0:
unauthenticated remote code execution through the Image Optimization
API when SVG files are used. progmasoft.com runs 16.3.8. The site sets
no images option and the optimizer refused an SVG request in a check
from outside, but the version is in the affected range, so it moves to
16.4.2, the latest patch release; eslint-config-next follows.

Verified: pnpm check, pnpm test:coverage, pnpm lint and pnpm build
pass; pnpm audit --audit-level high reports nothing beyond the one
advisory already ignored.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
pnpm audit reports a critical advisory for next &gt;=16.0.0 &lt;=16.4.0:
unauthenticated remote code execution through the Image Optimization
API when SVG files are used. progmasoft.com runs 16.3.8. The site sets
no images option and the optimizer refused an SVG request in a check
from outside, but the version is in the affected range, so it moves to
16.4.2, the latest patch release; eslint-config-next follows.

Verified: pnpm check, pnpm test:coverage, pnpm lint and pnpm build
pass; pnpm audit --audit-level high reports nothing beyond the one
advisory already ignored.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add Progmasoft OAuth, an OAuth 2.1 and OpenID Connect provider</title>
<updated>2026-10-23T01:49:52+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T01:49:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=cffc8d884ce3620b70c80a9ab98b8f1f03887402'/>
<id>cffc8d884ce3620b70c80a9ab98b8f1f03887402</id>
<content type='text'>
Progmasoft accounts can now sign in to any application, and any
developer can register one. The provider runs in the account API under
the Progmasoft.OAuth namespaces and answers on credentials.progmasoft.com.

Protocol: OpenIddict 7 (Apache-2.0) with its Entity Framework stores.
Authorization code with PKCE for every client, S256 only; refresh
tokens with rotation and no reuse leeway, so a replayed refresh token
revokes its chain; client credentials for confidential clients, without
account scopes. No implicit or password grant. Codes live 2 minutes,
access and identity tokens 15 minutes, refresh tokens 30 days. Signing
(RSA) and encryption keys are read from files in production and are
required there; other environments make keys per process.

Scopes, one grant each, as the consent page lists them: profile (the
account name), email (the sign-in address; email_verified is false,
since registration does not verify it), viget.packages.read,
viget.packages.publish and viget.packages.yank (access tokens for the
viget audience), and offline_access.

Pages, plain HTML without script, behind a content security policy that
allows the one stylesheet by digest: sign-in with the account password
(a cookie of its own, no account-site session), consent with the
application, its registering account and the return host, the developer
portal (register confidential or public clients, redirect address rules
from RFC 8252, scopes, client credentials, secret shown once and
rotatable, delete; 10 applications per account; other accounts'
applications are absent), and the applications an account has allowed,
with withdrawal that revokes their tokens. Forms carry antiforgery
tokens; return addresses stay on the host.

Storage: the oauth_* tables in the account database, created by a
numbered schema step like the account tables; the step is the script
Entity Framework generates for the model, and a test compares the two.
With the memory account store they live in a shared in-memory SQLite
database, which runs the bulk revocations the in-memory provider cannot.

A host filter keeps OAuth paths on the OAuth host and everything but
OAuth and /health off it. AllowedHosts names the new host, and a rate
limit policy covers the protocol endpoints and the portal. The Nginx
vhost for the host and the key set-up are in ops; docs/OAUTH.md is the
developer guide.

AccountService gains VerifyPasswordAsync, which LoginAsync now uses,
and FindAsync.

Verified: dotnet build with warnings as errors; dotnet test, 125 tests,
109 passed and 16 PostgreSQL tests skipped locally (CI runs them,
including a new one for the schema and refresh token chain revocation):
code flow with PKCE and the claims of each scope, single-use codes,
refresh rotation and reuse refusal, consent reuse and withdrawal, deny,
public client with a private-use scheme, client credentials, ViGet
audience by introspection, refusal without PKCE, of other flows and of
unpermitted scopes, unregistered redirect addresses, sign-in redirects
and prompt=none, the portal's address rules and ownership, secret
rotation, the page security policy, the host filter and the discovery
document.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Progmasoft accounts can now sign in to any application, and any
developer can register one. The provider runs in the account API under
the Progmasoft.OAuth namespaces and answers on credentials.progmasoft.com.

Protocol: OpenIddict 7 (Apache-2.0) with its Entity Framework stores.
Authorization code with PKCE for every client, S256 only; refresh
tokens with rotation and no reuse leeway, so a replayed refresh token
revokes its chain; client credentials for confidential clients, without
account scopes. No implicit or password grant. Codes live 2 minutes,
access and identity tokens 15 minutes, refresh tokens 30 days. Signing
(RSA) and encryption keys are read from files in production and are
required there; other environments make keys per process.

Scopes, one grant each, as the consent page lists them: profile (the
account name), email (the sign-in address; email_verified is false,
since registration does not verify it), viget.packages.read,
viget.packages.publish and viget.packages.yank (access tokens for the
viget audience), and offline_access.

Pages, plain HTML without script, behind a content security policy that
allows the one stylesheet by digest: sign-in with the account password
(a cookie of its own, no account-site session), consent with the
application, its registering account and the return host, the developer
portal (register confidential or public clients, redirect address rules
from RFC 8252, scopes, client credentials, secret shown once and
rotatable, delete; 10 applications per account; other accounts'
applications are absent), and the applications an account has allowed,
with withdrawal that revokes their tokens. Forms carry antiforgery
tokens; return addresses stay on the host.

Storage: the oauth_* tables in the account database, created by a
numbered schema step like the account tables; the step is the script
Entity Framework generates for the model, and a test compares the two.
With the memory account store they live in a shared in-memory SQLite
database, which runs the bulk revocations the in-memory provider cannot.

A host filter keeps OAuth paths on the OAuth host and everything but
OAuth and /health off it. AllowedHosts names the new host, and a rate
limit policy covers the protocol endpoints and the portal. The Nginx
vhost for the host and the key set-up are in ops; docs/OAUTH.md is the
developer guide.

AccountService gains VerifyPasswordAsync, which LoginAsync now uses,
and FindAsync.

Verified: dotnet build with warnings as errors; dotnet test, 125 tests,
109 passed and 16 PostgreSQL tests skipped locally (CI runs them,
including a new one for the schema and refresh token chain revocation):
code flow with PKCE and the claims of each scope, single-use codes,
refresh rotation and reuse refusal, consent reuse and withdrawal, deny,
public client with a private-use scheme, client credentials, ViGet
audience by introspection, refusal without PKCE, of other flows and of
unpermitted scopes, unregistered redirect addresses, sign-in redirects
and prompt=none, the portal's address rules and ownership, secret
rotation, the page security policy, the host filter and the discovery
document.
</pre>
</div>
</content>
</entry>
<entry>
<title>Harden the systemd units of the API and the web frontend</title>
<updated>2026-10-23T00:21:38+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T00:21:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=11d91cba681e48afe0fcec6640d07b9100301f86'/>
<id>11d91cba681e48afe0fcec6640d07b9100301f86</id>
<content type='text'>
systemd-analyze security rated both services 7.2 MEDIUM. They now
carry the restrictions the Tala website API already runs with: no
capabilities (empty bounding and ambient sets), private /dev, no
access to the clock, hostname, kernel logs, modules, tunables or
control groups, only AF_UNIX/AF_INET/AF_INET6 sockets, no new
namespaces, no realtime scheduling, IPC removed on stop, and a 0077
umask. MemoryDenyWriteExecute stays off, since CoreCLR and V8 JIT
need writable executable mappings.

Deployed and verified on the server: systemd-analyze verify is clean,
both services restarted and rate 3.0 OK, the API health endpoint and
the frontend answer 200 on loopback, and progmasoft.com,
account.progmasoft.com and viget.progmasoft.com answer 200.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
systemd-analyze security rated both services 7.2 MEDIUM. They now
carry the restrictions the Tala website API already runs with: no
capabilities (empty bounding and ambient sets), private /dev, no
access to the clock, hostname, kernel logs, modules, tunables or
control groups, only AF_UNIX/AF_INET/AF_INET6 sockets, no new
namespaces, no realtime scheduling, IPC removed on stop, and a 0077
umask. MemoryDenyWriteExecute stays off, since CoreCLR and V8 JIT
need writable executable mappings.

Deployed and verified on the server: systemd-analyze verify is clean,
both services restarted and rate 3.0 OK, the API health endpoint and
the frontend answer 200 on loopback, and progmasoft.com,
account.progmasoft.com and viget.progmasoft.com answer 200.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #41 from Progmasoft/web/bimi-logo</title>
<updated>2026-10-18T16:10:32+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-10-18T16:10:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=46e526f91e805319e0b0b65bae8d09dc4fabfa0c'/>
<id>46e526f91e805319e0b0b65bae8d09dc4fabfa0c</id>
<content type='text'>
Serve the Progmasoft mark as a BIMI logo</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Serve the Progmasoft mark as a BIMI logo</pre>
</div>
</content>
</entry>
</feed>
