<feed xmlns='http://www.w3.org/2005/Atom'>
<title>progmaweb/apps, branch feature/five-part-versions</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>Accept plugin versions of up to five numbers</title>
<updated>2026-11-01T17:16:35+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T17:16:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=e85e2b2359518f83354c09f9f4a101b7779e6e9c'/>
<id>e85e2b2359518f83354c09f9f4a101b7779e6e9c</id>
<content type='text'>
Tazel takes A.B.C, then .D, .E and -METADATA if needed, so the descriptor
check follows it.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Tazel takes A.B.C, then .D, .E and -METADATA if needed, so the descriptor
check follows it.
</pre>
</div>
</content>
</entry>
<entry>
<title>Accept plugin versions of four numbers</title>
<updated>2026-11-01T13:09:24+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-11-01T13:09:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=02662c79c1f2bcda974da9e1b0ed8c5ac92ee127'/>
<id>02662c79c1f2bcda974da9e1b0ed8c5ac92ee127</id>
<content type='text'>
Progmasoft's releases move to four numbers, and the plugins publish here.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Progmasoft's releases move to four numbers, and the plugins publish here.
</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>Provision the reserved accounts on the server</title>
<updated>2026-10-29T12:35:06+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T12:35:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=21b515565b73f86477afe436bb3588f3e5929443'/>
<id>21b515565b73f86477afe436bb3588f3e5929443</id>
<content type='text'>
Registration refuses the reserved names Progmasoft and Leitwolf, which are
meant to be created by trusted operations tooling only, and that tooling did
not exist: the Progmasoft account, the publisher of Progmasoft's Tazel
plugins on ViGet, could not be created at all.

- 'accounts provision-reserved &lt;Name&gt; &lt;email&gt;' runs with the configuration
  of the service, like the viget commands. It accepts only the reserved
  names, applies the rules of registration to the email address and the
  password, never replaces an existing account, and brings the account
  tables to the current schema first.
- The password is read from the terminal without echo, twice, or from one
  line of standard input when it is not a terminal; it never appears on a
  command line or in the output.
- AccountNamePolicy.TryNormalizeReserved checks a reserved name;
  TryNormalize, which registration uses, still refuses it.

Tests cover a reserved account created and signing in with its password,
a name that is not reserved, two different passwords, a weak password, an
existing account and the usage line. ops/README.md shows the command with
systemd-run --pty; docs/ACCOUNT-API.md points to it.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Registration refuses the reserved names Progmasoft and Leitwolf, which are
meant to be created by trusted operations tooling only, and that tooling did
not exist: the Progmasoft account, the publisher of Progmasoft's Tazel
plugins on ViGet, could not be created at all.

- 'accounts provision-reserved &lt;Name&gt; &lt;email&gt;' runs with the configuration
  of the service, like the viget commands. It accepts only the reserved
  names, applies the rules of registration to the email address and the
  password, never replaces an existing account, and brings the account
  tables to the current schema first.
- The password is read from the terminal without echo, twice, or from one
  line of standard input when it is not a terminal; it never appears on a
  command line or in the output.
- AccountNamePolicy.TryNormalizeReserved checks a reserved name;
  TryNormalize, which registration uses, still refuses it.

Tests cover a reserved account created and signing in with its password,
a name that is not reserved, two different passwords, a weak password, an
existing account and the usage line. ops/README.md shows the command with
systemd-run --pty; docs/ACCOUNT-API.md points to it.
</pre>
</div>
</content>
</entry>
<entry>
<title>Let the API answer for viget.progmasoft.com</title>
<updated>2026-10-29T10:20:18+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T10:20:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=06b384e0b46aa74c36e48dbe86e0e453d975d012'/>
<id>06b384e0b46aa74c36e48dbe86e0e453d975d012</id>
<content type='text'>
Nginx passes https://viget.progmasoft.com/dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/index.json
to the API with the host of the request, and host filtering refused it with
400: viget.progmasoft.com was missing from AllowedHosts. The index is what
Tazel reads to download a plugin.

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>
Nginx passes https://viget.progmasoft.com/dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/index.json
to the API with the host of the request, and host filtering refused it with
400: viget.progmasoft.com was missing from AllowedHosts. The index is what
Tazel reads to download a plugin.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Document the ViGet API in full and take zod 4.6.7 for eslint</title>
<updated>2026-10-29T09:42:13+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T09:42:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=285e1024da64234b30b0fa425ffd6bf348119db4'/>
<id>285e1024da64234b30b0fa425ffd6bf348119db4</id>
<content type='text'>
The documentation check of the backend found the private members of
ViGet/ without a summary and no page for its namespace:
- Summaries for every field and helper method of the catalog, the
  descriptor, the properties reader, publishing and the endpoints.
- docs/api/namespaces/Progmasoft.Progmaweb.Api.ViGet.md describes the
  namespace.
- The two regular expressions of TazelPluginDescriptor are excluded from the
  reference like AccountNamePolicy.CanonicalPattern: the generator replaces
  their comment with its own.

The dependency audit found GHSA for zod &lt; 4.6.6, which can exhaust memory
while validating oversized constrained collections. Only
eslint-plugin-react-hooks reaches it, and it accepts any zod 4, so an
override takes 4.6.7 until the plugin resolves a fixed release itself.
pnpm audit --audit-level high finds nothing.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The documentation check of the backend found the private members of
ViGet/ without a summary and no page for its namespace:
- Summaries for every field and helper method of the catalog, the
  descriptor, the properties reader, publishing and the endpoints.
- docs/api/namespaces/Progmasoft.Progmaweb.Api.ViGet.md describes the
  namespace.
- The two regular expressions of TazelPluginDescriptor are excluded from the
  reference like AccountNamePolicy.CanonicalPattern: the generator replaces
  their comment with its own.

The dependency audit found GHSA for zod &lt; 4.6.6, which can exhaust memory
while validating oversized constrained collections. Only
eslint-plugin-react-hooks reaches it, and it accepts any zod 4, so an
override takes 4.6.7 until the plugin resolves a fixed release itself.
pnpm audit --audit-level high finds nothing.
</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>Add the Tazel plugin catalog of ViGet to the API</title>
<updated>2026-10-29T06:53:57+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-29T06:53:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=58fa0d19d223aaebf9973ebd446c4bb855351ef9'/>
<id>58fa0d19d223aaebf9973ebd446c4bb855351ef9</id>
<content type='text'>
ViGet opens in stages: first only Progmasoft publishes Tazel plugins, later
every account. This adds the catalog and the server-side publishing for the
first stage; nothing publishes through the API yet.

- ViGet/: the catalog of Tazel plugins (in memory, or in PostgreSQL beside
  the accounts with its own numbered schema steps), the descriptor read from
  the JAR (META-INF/tazel-plugin.properties, with a reader of the Java
  properties format, and the ProjectPlugin service entry), and publishing:
  the publisher must be in ViGet:TazelPublishers (Progmasoft for now) and an
  existing account of that exact name, a version is never replaced, names
  that differ only in letter case are refused, and ViGet needs a
  description, an author and a license. The JAR is kept at
  dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/&lt;Version&gt;/&lt;Name&gt;-&lt;Version&gt;.jar below
  ViGet:ArtifactRoot.
- Read endpoints under /api/v1/viget/dslplugins/tazel: the list, a plugin,
  and index.json, the index Tazel reads.
- 'viget publish-tazel-plugin &lt;jar&gt;' and 'viget yank-tazel-plugin' run with
  the configuration of the service instead of the service.
- The account store can find an account by name.

The pages, the Nginx routes and the deployment follow.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
ViGet opens in stages: first only Progmasoft publishes Tazel plugins, later
every account. This adds the catalog and the server-side publishing for the
first stage; nothing publishes through the API yet.

- ViGet/: the catalog of Tazel plugins (in memory, or in PostgreSQL beside
  the accounts with its own numbered schema steps), the descriptor read from
  the JAR (META-INF/tazel-plugin.properties, with a reader of the Java
  properties format, and the ProjectPlugin service entry), and publishing:
  the publisher must be in ViGet:TazelPublishers (Progmasoft for now) and an
  existing account of that exact name, a version is never replaced, names
  that differ only in letter case are refused, and ViGet needs a
  description, an author and a license. The JAR is kept at
  dslplugins/tazel/&lt;Publisher&gt;/&lt;Name&gt;/&lt;Version&gt;/&lt;Name&gt;-&lt;Version&gt;.jar below
  ViGet:ArtifactRoot.
- Read endpoints under /api/v1/viget/dslplugins/tazel: the list, a plugin,
  and index.json, the index Tazel reads.
- 'viget publish-tazel-plugin &lt;jar&gt;' and 'viget yank-tazel-plugin' run with
  the configuration of the service instead of the service.
- The account store can find an account by name.

The pages, the Nginx routes and the deployment follow.
</pre>
</div>
</content>
</entry>
<entry>
<title>Let the second proxy pass through a site's own tree</title>
<updated>2026-10-23T08:41:06+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T08:41:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=85bdf1aba26641bf90da84fd6ce642ac41a6e73e'/>
<id>85bdf1aba26641bf90da84fd6ce642ac41a6e73e</id>
<content type='text'>
The standalone server, which production runs, invokes the proxy again for
the rewritten path with the original host. A path already inside the
site's internal tree (/authorize/signin on authorize.progmasoft.com) did
not match the public routes and became the site's not-found page, so
every OAuth, console and product page answered 404 in production while
next start, which runs the proxy once, served them. A path under the
site's own root now passes unchanged; internal trees stay closed on every
other host. Checked against the standalone build for all hosts.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The standalone server, which production runs, invokes the proxy again for
the rewritten path with the original host. A path already inside the
site's internal tree (/authorize/signin on authorize.progmasoft.com) did
not match the public routes and became the site's not-found page, so
every OAuth, console and product page answered 404 in production while
next start, which runs the proxy once, served them. A path under the
site's own root now passes unchanged; internal trees stay closed on every
other host. Checked against the standalone build for all hosts.
</pre>
</div>
</content>
</entry>
<entry>
<title>Describe talalint by what version 0.1.0 does</title>
<updated>2026-10-23T08:31:48+00:00</updated>
<author>
<name>Leitwolf11</name>
</author>
<published>2026-10-23T08:31:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.progmasoft.com/progmaweb/commit/?id=6e871a697f64d3460e838bff19a52637faf22f08'/>
<id>6e871a697f64d3460e838bff19a52637faf22f08</id>
<content type='text'>
The catalog said talalint reads talalint.kts. Its Kotlin module defines
the configuration model but does not yet discover or evaluate the script,
so the page now lists what the linter does today: the diagnostics of the
Tala compiler under the compiler check, its own checks of trailing
whitespace, mixed line endings and the final newline, and --fix limited
to safe physical-source fixes.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The catalog said talalint reads talalint.kts. Its Kotlin module defines
the configuration model but does not yet discover or evaluate the script,
so the page now lists what the linter does today: the diagnostics of the
Tala compiler under the compiler check, its own checks of trailing
whitespace, mixed line endings and the final newline, and --fix limited
to safe physical-source fixes.
</pre>
</div>
</content>
</entry>
</feed>
