<feed xmlns='http://www.w3.org/2005/Atom'>
<title>progmaweb/apps/web/app, branch main</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>Remove Xide and ides.progmasoft.com</title>
<updated>2026-11-08T15:46:08+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-08T15:46:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=efa1f584205e93c292ea40b564d92a03f12ab33c'/>
<id>efa1f584205e93c292ea40b564d92a03f12ab33c</id>
<content type='text'>
Xide is no longer developed as of 2026-11-08 (Progmasoft/xide#29), so
Progmaweb stops presenting it:

- product.progmasoft.com: Xide leaves the catalog, its card and its
  detail page; /xide on the product host is a 404 like any unknown
  product. The catalog's description in every language names the Tala
  language with its tools and Catch3.
- ides.progmasoft.com served only the IDE list and the Xide page, so the
  whole site goes: the pages under app/ides, its texts in every
  language, idesRoute and its host in the proxy, and both nginx server
  blocks. The certificate of progmasoft.com no longer has to name it.

Tests: the catalog lists the remaining products and refuses xide.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Xide is no longer developed as of 2026-11-08 (Progmasoft/xide#29), so
Progmaweb stops presenting it:

- product.progmasoft.com: Xide leaves the catalog, its card and its
  detail page; /xide on the product host is a 404 like any unknown
  product. The catalog's description in every language names the Tala
  language with its tools and Catch3.
- ides.progmasoft.com served only the IDE list and the Xide page, so the
  whole site goes: the pages under app/ides, its texts in every
  language, idesRoute and its host in the proxy, and both nginx server
  blocks. The certificate of progmasoft.com no longer has to name it.

Tests: the catalog lists the remaining products and refuses xide.
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch 'main' into feature/policies-consent</title>
<updated>2026-11-06T14:51:08+00:00</updated>
<author>
<name>Leitwolf</name>
</author>
<published>2026-11-06T14:51:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=52047af6589b2729575523c1f4db61ea90a35d30'/>
<id>52047af6589b2729575523c1f4db61ea90a35d30</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Ask for the Privacy and Security Policies at registration</title>
<updated>2026-11-06T09:57:27+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-06T09:57:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=53fb8b8bde857025d12655ae53857fc30226b186'/>
<id>53fb8b8bde857025d12655ae53857fc30226b186</id>
<content type='text'>
progmasoft.com/privacy and progmasoft.com/security publish the two
policies in en-US, de-DE, ru-RU and he-IL, and the footer links both.
The Privacy Policy says what an account keeps and that Progmasoft keeps
an IP address for one purpose only: with a ViGet upload, to establish
where an upload that turns out to be malicious software came from and
to give it to the competent authorities. It says that no data, the IP
address included, is sold, rented or traded. The Security Policy covers
passwords, sessions, HTTPS, the ban on malicious software in ViGet and
how to report a weakness.

The registration form asks the person to accept both policies, and the
API refuses a registration without that acceptance, with a password
(acceptPolicies, a validation error of that field) or through Google:
the start of a Google registration without acceptPolicies=true goes
back to /register?google=policies-required, and the completion creates
no account unless the authentication state carries the current version.
An account keeps the version it accepted and the moment, in two new
columns that schema step 2 adds; accounts created before it keep null.
PolicyAcceptance.CurrentVersion and policyVersion on the web side name
the same date, and a web test reads the C# constant to keep them equal.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
progmasoft.com/privacy and progmasoft.com/security publish the two
policies in en-US, de-DE, ru-RU and he-IL, and the footer links both.
The Privacy Policy says what an account keeps and that Progmasoft keeps
an IP address for one purpose only: with a ViGet upload, to establish
where an upload that turns out to be malicious software came from and
to give it to the competent authorities. It says that no data, the IP
address included, is sold, rented or traded. The Security Policy covers
passwords, sessions, HTTPS, the ban on malicious software in ViGet and
how to report a weakness.

The registration form asks the person to accept both policies, and the
API refuses a registration without that acceptance, with a password
(acceptPolicies, a validation error of that field) or through Google:
the start of a Google registration without acceptPolicies=true goes
back to /register?google=policies-required, and the completion creates
no account unless the authentication state carries the current version.
An account keeps the version it accepted and the moment, in two new
columns that schema step 2 adds; accounts created before it keep null.
PolicyAcceptance.CurrentVersion and policyVersion on the web side name
the same date, and a web test reads the C# constant to keep them equal.
</pre>
</div>
</content>
</entry>
<entry>
<title>Link Tazel's site at tazel.net</title>
<updated>2026-11-06T06:44:08+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-06T06:44:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=ed8dc99ef0910ae9c9797918775d18786e0a9f1b'/>
<id>ed8dc99ef0910ae9c9797918775d18786e0a9f1b</id>
<content type='text'>
tazel.tala.run only redirects to tazel.net now. The product list and the
Tazel plugin catalog link the new address directly.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
tazel.tala.run only redirects to tazel.net now. The product list and the
Tazel plugin catalog link the new address directly.
</pre>
</div>
</content>
</entry>
<entry>
<title>Give every page a Content-Security-Policy with its own nonce</title>
<updated>2026-11-06T05:05:21+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-06T05:05:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=c4fb3effa7f806c570771bb83c0ed6988006bc24'/>
<id>c4fb3effa7f806c570771bb83c0ed6988006bc24</id>
<content type='text'>
The pages of progmasoft.com and its hosts had no content security
policy. The proxy now creates a 128-bit nonce for every request and sends
the policy both ways: on the request, so that Next marks its own inline
scripts with the nonce, and on the response. The layout reads the nonce
for the theme bootstrap. Every page is rendered on demand already, so
none is served with a stale nonce.

Scripts may come from the host, carry the nonce, or be Cloudflare's Web
Analytics beacon from static.cloudflareinsights.com, which reports to
cloudflareinsights.com. 'strict-dynamic' is left out, because browsers
ignore host sources under it and the beacon is added by Cloudflare
without a nonce. Styles allow inline ones; objects, framing and other
base URLs are refused. There is no form-action: sign-in and OAuth
consent end in redirects to other hosts, loopback addresses included,
and browsers apply form-action to them. The development server also
gets 'unsafe-eval' for its hot reload.

Tests check the nonce and each directive; ARCHITECTURE.md describes the
policy.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The pages of progmasoft.com and its hosts had no content security
policy. The proxy now creates a 128-bit nonce for every request and sends
the policy both ways: on the request, so that Next marks its own inline
scripts with the nonce, and on the response. The layout reads the nonce
for the theme bootstrap. Every page is rendered on demand already, so
none is served with a stale nonce.

Scripts may come from the host, carry the nonce, or be Cloudflare's Web
Analytics beacon from static.cloudflareinsights.com, which reports to
cloudflareinsights.com. 'strict-dynamic' is left out, because browsers
ignore host sources under it and the beacon is added by Cloudflare
without a nonce. Styles allow inline ones; objects, framing and other
base URLs are refused. There is no form-action: sign-in and OAuth
consent end in redirects to other hosts, loopback addresses included,
and browsers apply form-action to them. The development server also
gets 'unsafe-eval' for its hot reload.

Tests check the nonce and each directive; ARCHITECTURE.md describes the
policy.
</pre>
</div>
</content>
</entry>
<entry>
<title>Serve the Progmasoft mark as the site icon</title>
<updated>2026-10-29T15:25:16+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T15:25:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=6a87306ec5b972cbf18d76836a6df5d7828575ea'/>
<id>6a87306ec5b972cbf18d76836a6df5d7828575ea</id>
<content type='text'>
The sites declared no icon and /favicon.ico answered 404, so search
engines and assistants that show a site's icon (DuckDuckGo, ChatGPT)
fell back to a gray placeholder; the only copy of the mark was the BIMI
logo for mail.

The app now has the Next.js icon files, so every page links them:

- app/icon.svg: the four squares of the BIMI logo, cropped to the mark
  so it fills a browser tab, on a transparent field.
- app/favicon.ico: the same mark at 16, 32 and 48 pixels (PNG entries),
  for clients that ask for /favicon.ico without reading the page.
- app/apple-icon.png: 180 pixels on the white field of the BIMI logo,
  since iOS fills transparency with black.

The proxy rewrites paths per host, which would send /icon.svg on the
account, ViGet and the other hosts into their own page trees; the
matcher now skips the two new files as it already skipped favicon.ico,
so every Progmasoft host serves the same icons.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The sites declared no icon and /favicon.ico answered 404, so search
engines and assistants that show a site's icon (DuckDuckGo, ChatGPT)
fell back to a gray placeholder; the only copy of the mark was the BIMI
logo for mail.

The app now has the Next.js icon files, so every page links them:

- app/icon.svg: the four squares of the BIMI logo, cropped to the mark
  so it fills a browser tab, on a transparent field.
- app/favicon.ico: the same mark at 16, 32 and 48 pixels (PNG entries),
  for clients that ask for /favicon.ico without reading the page.
- app/apple-icon.png: 180 pixels on the white field of the BIMI logo,
  since iOS fills transparency with black.

The proxy rewrites paths per host, which would send /icon.svg on the
account, ViGet and the other hosts into their own page trees; the
matcher now skips the two new files as it already skipped favicon.ico,
so every Progmasoft host serves the same icons.
</pre>
</div>
</content>
</entry>
<entry>
<title>Show the Tazel plugins of ViGet, open the Gradle catalog, and route their files</title>
<updated>2026-10-29T09:32:23+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T09:32:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=3d1c6d52b830d201a68b0440a8a81c13b74c8b92'/>
<id>3d1c6d52b830d201a68b0440a8a81c13b74c8b92</id>
<content type='text'>
The API of the previous commit holds the catalog; this adds what people and
Tazel reach.

Pages:
- /dslplugins/tazel lists the published plugins, read from the API on its
  loopback address, and says when there is none.
- /dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt; is the page of a plugin: its
  description, publisher, latest version, license, authors, homepage and
  repository, the plugins block that uses it, and every version with its
  date, plugin API, size, SHA-256, yanked mark and JAR.
- /dslplugins/gradle opens the Gradle catalog. It only lists: Gradle takes
  com.progmasoft.tazel.plugin from the Gradle Plugin Portal.
- The availability note says that Progmasoft publishes first and every
  account later. Texts are in the four languages of the site.

Nginx (ops/nginx/progmaweb.conf):
- On viget.progmasoft.com, index.json of a plugin goes to the API and the
  JARs come from /srv/viget/files with immutable caching; /api/ stays
  closed.
- maven.progmasoft.com serves /srv/maven, whose /tazel holds tazel-api.

ops/README.md describes the directories, their SELinux labels, the publish
and yank commands, and how a release of Tazel copies the API into the Maven
repository.

Tests cover the texts in every language, the plugins block, the Gradle list,
and that a page asks the API only for identifiers.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The API of the previous commit holds the catalog; this adds what people and
Tazel reach.

Pages:
- /dslplugins/tazel lists the published plugins, read from the API on its
  loopback address, and says when there is none.
- /dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt; is the page of a plugin: its
  description, publisher, latest version, license, authors, homepage and
  repository, the plugins block that uses it, and every version with its
  date, plugin API, size, SHA-256, yanked mark and JAR.
- /dslplugins/gradle opens the Gradle catalog. It only lists: Gradle takes
  com.progmasoft.tazel.plugin from the Gradle Plugin Portal.
- The availability note says that Progmasoft publishes first and every
  account later. Texts are in the four languages of the site.

Nginx (ops/nginx/progmaweb.conf):
- On viget.progmasoft.com, index.json of a plugin goes to the API and the
  JARs come from /srv/viget/files with immutable caching; /api/ stays
  closed.
- maven.progmasoft.com serves /srv/maven, whose /tazel holds tazel-api.

ops/README.md describes the directories, their SELinux labels, the publish
and yank commands, and how a release of Tazel copies the API into the Maven
repository.

Tests cover the texts in every language, the plugins block, the Gradle list,
and that a page asks the API only for identifiers.
</pre>
</div>
</content>
</entry>
<entry>
<title>Redesign progmasoft.com and add the product catalog and product sites</title>
<updated>2026-10-23T08:29:43+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T08:29:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=20a55c4ccbb0f181346444a4c7f083e86389cf9c'/>
<id>20a55c4ccbb0f181346444a4c7f083e86389cf9c</id>
<content type='text'>
progmasoft.com presents Progmasoft as a pool of technology areas instead
of a list of products: languages and compilers, build and packages,
developer tools, quality and testing, identity and access, and
infrastructure. The page has a new hero, a bento of areas, principles and
a developers band that leads to the Progmasoft Console; the products are
one link away in their own catalog.

product.progmasoft.com lists Tala, talac, talafmt, talalint, Tazel, Xide
and Catch3, each with its own page (/tala-lang, /talac, ...) that leads
to the product's site and source. ides.progmasoft.com lists the IDEs and
hosts the Xide site at /xide; catch3.progmasoft.com is the Catch3 site.
The facts follow the READMEs and documentation of the product
repositories: Xide is marked as early work, and Catch3 states that it is
not an official Catch2 release.

The theme switch no longer freezes or flickers. The layout rendered
data-theme="light" on &lt;html&gt;, so every server re-render of the layout
(a language switch) set it back. The control also applied the theme in
an effect after the render while buttons animated their colours. The
attribute now belongs to the bootstrap script and the control alone; the
control applies the theme in the click, and transitions are off for the
two frames of the change.

All new text is in en-US, de-DE, ru-RU and he-IL. The old home messages
leave localization.ts. The proxy maps the new hosts through one table, and
nginx gains their virtual hosts.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
progmasoft.com presents Progmasoft as a pool of technology areas instead
of a list of products: languages and compilers, build and packages,
developer tools, quality and testing, identity and access, and
infrastructure. The page has a new hero, a bento of areas, principles and
a developers band that leads to the Progmasoft Console; the products are
one link away in their own catalog.

product.progmasoft.com lists Tala, talac, talafmt, talalint, Tazel, Xide
and Catch3, each with its own page (/tala-lang, /talac, ...) that leads
to the product's site and source. ides.progmasoft.com lists the IDEs and
hosts the Xide site at /xide; catch3.progmasoft.com is the Catch3 site.
The facts follow the READMEs and documentation of the product
repositories: Xide is marked as early work, and Catch3 states that it is
not an official Catch2 release.

The theme switch no longer freezes or flickers. The layout rendered
data-theme="light" on &lt;html&gt;, so every server re-render of the layout
(a language switch) set it back. The control also applied the theme in
an effect after the render while buttons animated their colours. The
attribute now belongs to the bootstrap script and the control alone; the
control applies the theme in the click, and transitions are off for the
two frames of the change.

All new text is in en-US, de-DE, ru-RU and he-IL. The old home messages
leave localization.ts. The proxy maps the new hosts through one table, and
nginx gains their virtual hosts.
</pre>
</div>
</content>
</entry>
<entry>
<title>Move the OAuth pages to Next.js and split the authorize host and the console</title>
<updated>2026-10-23T08:02:39+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T08:02:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=9099e9fbb50d27b622362b0c2f0dda5085d1fa03'/>
<id>9099e9fbb50d27b622362b0c2f0dda5085d1fa03</id>
<content type='text'>
Progmasoft OAuth now runs on three hosts:

- credentials.progmasoft.com stays the issuer: discovery documents, key
  set, token, user information, revocation and introspection.
- authorize.progmasoft.com serves the pages people see: the
  authorization and end session endpoints (registered with OpenIddict as
  absolute URIs on that host), sign-in, the consent screen and the
  applications an account has allowed.
- console.progmasoft.com is the Progmasoft Console. Its overview links
  the areas; OAuth 2.1 tokens live under /credentials, with New token,
  then the application type, then its form.

The console has no sign-in of its own and never redirects. It uses the
Progmasoft account session, so production now shares that cookie with
progmasoft.com (__Secure-ProgmasoftSession, Domain=progmasoft.com,
HttpOnly, Secure, SameSite=Lax). Without AccountSessions:CookieDomain the
cookie stays host-only with the __Host- name, as in development and tests.

Application types replace the confidential/public switch: web,
single-page, desktop, mobile and service. Each type has its redirection
rules (RFC 8252), its secret or none, and its grants; only a service
uses client credentials and it registers no address or scope. The type is
kept as an application property and cannot change.

The HTML pages of the API are gone. The pages are Next.js pages in four
languages (en-US, de-DE, ru-RU, he-IL) that call JSON endpoints under
/api/v1/oauth. Requests that change state must come from the page's own
origin; antiforgery forms are no longer needed. The token, revocation and
user information endpoints answer CORS requests from the origins of
single-page applications, without credentials; the discovery documents
and the key set answer every origin.

The host filter keeps every path on its host. Nginx gains the authorize
and console virtual hosts, and the docs describe the hosts, the types and
the shared session.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Progmasoft OAuth now runs on three hosts:

- credentials.progmasoft.com stays the issuer: discovery documents, key
  set, token, user information, revocation and introspection.
- authorize.progmasoft.com serves the pages people see: the
  authorization and end session endpoints (registered with OpenIddict as
  absolute URIs on that host), sign-in, the consent screen and the
  applications an account has allowed.
- console.progmasoft.com is the Progmasoft Console. Its overview links
  the areas; OAuth 2.1 tokens live under /credentials, with New token,
  then the application type, then its form.

The console has no sign-in of its own and never redirects. It uses the
Progmasoft account session, so production now shares that cookie with
progmasoft.com (__Secure-ProgmasoftSession, Domain=progmasoft.com,
HttpOnly, Secure, SameSite=Lax). Without AccountSessions:CookieDomain the
cookie stays host-only with the __Host- name, as in development and tests.

Application types replace the confidential/public switch: web,
single-page, desktop, mobile and service. Each type has its redirection
rules (RFC 8252), its secret or none, and its grants; only a service
uses client credentials and it registers no address or scope. The type is
kept as an application property and cannot change.

The HTML pages of the API are gone. The pages are Next.js pages in four
languages (en-US, de-DE, ru-RU, he-IL) that call JSON endpoints under
/api/v1/oauth. Requests that change state must come from the page's own
origin; antiforgery forms are no longer needed. The token, revocation and
user information endpoints answer CORS requests from the origins of
single-page applications, without credentials; the discovery documents
and the key set answer every origin.

The host filter keeps every path on its host. Nginx gains the authorize
and console virtual hosts, and the docs describe the hosts, the types and
the shared session.
</pre>
</div>
</content>
</entry>
<entry>
<title>Group ViGet by language and by build system</title>
<updated>2026-10-15T15:18:50+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-15T15:18:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=16b47e37e2d00b5f9bf0c83c1c03cc6a0991f1c4'/>
<id>16b47e37e2d00b5f9bf0c83c1c03cc6a0991f1c4</id>
<content type='text'>
viget.progmasoft.com now shows, from the top:

1. The state of the registry: what it holds today, the package format,
   the publisher identity and that publishing is not open yet.
2. LANGUAGES: Tala links to viget.progmasoft.com/langs/tala; C++ is a
   gray, disabled button that leads nowhere.
3. BUILD SYSTEM DSL PLUGINS: Tazel links to
   viget.progmasoft.com/dslplugins/tazel; Gradle is a gray, disabled
   button that leads nowhere.

/langs/tala is the catalog of Tala packages and /dslplugins/tazel the
catalog of Kotlin DSL plugins for Tazel, both honestly empty. /langs and
/dslplugins redirect to them. The header, the footer and the sitemap
link the two catalogs, and the coordinates they show begin with the
catalog: /langs/tala/&lt;Publisher&gt;/&lt;Name&gt;/ and
/dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/.

The text of the catalogs lives in lib/viget-catalogs.ts in all four
locales; localization.ts is close to the size limit of a file. The
two section headings are the registry's names and stay in English.

The language links of the ViGet and Progmasoft pages point at tala.run.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
viget.progmasoft.com now shows, from the top:

1. The state of the registry: what it holds today, the package format,
   the publisher identity and that publishing is not open yet.
2. LANGUAGES: Tala links to viget.progmasoft.com/langs/tala; C++ is a
   gray, disabled button that leads nowhere.
3. BUILD SYSTEM DSL PLUGINS: Tazel links to
   viget.progmasoft.com/dslplugins/tazel; Gradle is a gray, disabled
   button that leads nowhere.

/langs/tala is the catalog of Tala packages and /dslplugins/tazel the
catalog of Kotlin DSL plugins for Tazel, both honestly empty. /langs and
/dslplugins redirect to them. The header, the footer and the sitemap
link the two catalogs, and the coordinates they show begin with the
catalog: /langs/tala/&lt;Publisher&gt;/&lt;Name&gt;/ and
/dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/.

The text of the catalogs lives in lib/viget-catalogs.ts in all four
locales; localization.ts is close to the size limit of a file. The
two section headings are the registry's names and stay in English.

The language links of the ViGet and Progmasoft pages point at tala.run.
</pre>
</div>
</content>
</entry>
</feed>
