Skip to content

SoftN v0.0.31

Latest

Choose a tag to compare

@github-actions github-actions released this 01 Nov 22:30

SoftN v0.0.31

What's new

  • Upgrading, and act on this if your site runs on nginx: the nginx.conf.example in every release so far lets anyone download your site's data/ folder, which holds the admin key, every published bundle (hidden apps' too), comments and the records apps keep on the server. The rule that looks as if it refuses the folder does not: nginx prefers a regular expression to a plain prefix, so /data/config.json was served as an ordinary file. If you copied that example into your nginx configuration, find the line location /data/ { return 404; }, put these two lines in its place, and reload nginx (sudo nginx -t, then sudo systemctl reload nginx): location = /data { return 404; } and location ^~ /data/ { return 404; }. Or replace your copy's whole server { } block with the new example and put your server_name, root and TLS back, which also brings the other changes below. Check it from outside: curl -s -o /dev/null -w "%{http_code}\n" https://your.site/data/README.txt must print 404. That file is in every site, and answered 200 before. Then treat the admin key as seen by others: put a new value in adminKey in data/config.json (the next request reads it), and look in your access log for requests under /data/. If anyone took the folder, they can also work out the IPv4 address of each visitor who commented or rated, because the salt in that same file is what hides them; tell your visitors if that matters where you are. Leave salt as it is: replacing it undoes nothing already taken, and it cuts visitors off from the records apps keep for them. Edit keys need no replacing: only their hashes are in that folder, and those cannot be reversed. A site on Apache with the shipped .htaccess was not affected.
  • Upgrading from v0.0.30: the engine is still ZIPP v0.0.32, so nothing is rebuilt, and FormLogic's adapter and every protocol number are v0.0.30's. Take the new .htaccess or nginx.conf.example along with the files: most of what is below about what a server serves is in those.
  • Files nobody meant to publish are not served, wherever in the site they were left. The site's .htaccess had no rule for dot files, so on Apache /.git/config and /.env were plain downloads wherever a folder held them. So were both in the static single-app package; the host and private packages refused .env and not .git/config, because FilesMatch looks at a file's own name and at no folder in its path. All of them now refuse any dot file or dot folder but /.well-known/, which a certificate's challenge needs. The site on both servers, the packages on Apache (with mod_alias, which is on by default) and the nginx blocks in their guides also refuse a file named config.json, and one ending in .zip, .tar, .tar.gz, .tgz, .sql, .sql.gz, .sqlite, .db, .bak, .old, .orig or .save, in capitals or not. An address under the site's own /api/ is a route and is not touched; a folder called api further down is no exception. A site that does mean to offer such a file, a .zip to download say, must take that one rule out of its copy. Those nginx blocks no longer send a stray .php file's source. DEPLOY.md says to keep a backup of data/ outside the document root, and gives the check to run after an upload. The tests now run all of this on a real Apache and a real nginx, the guides' blocks included.
  • FormLogic: a loop of writes to one collection is not refused. XDB keeps a collection under one key, so each record added wrote the whole collection again, and the frame holds 32 saves: the 33rd was refused as a full store with room to spare. The save last in the queue now takes a newer value of the same key, with that value's deadline, and every receipt says what became of it. A save already handed over is never changed, keys land in the order they were written, and a parent on protocol 0 gets every write as before. Writes that take turns between collections cannot merge, so the 33rd of those is still refused while the queue is full.
  • FormLogic: a store that refuses a write says so in the frame, where the parent confirms saves. A collection in FormLogic's browser storage holds 30,000 characters, and past it the app's write failed with nothing on screen. The note goes once a save of that collection goes through. The records an app ships with are no save of anyone's: if they do not fit, the app opens without them and no note stands over it.
  • A deleted record gives its room back. It keeps its place for sync, which reads its id and stamp, and it kept its data too, so deleting freed nothing and a full store stayed full. When the store refuses a save, the data of deleted records goes, in every collection, because the limit is shared, and the save is tried again. While there is room they stay whole. In FormLogic's frame, where no sync can reach the store, the rows go too: an emptied row still costs about 170 characters, so an app that added and deleted small records ended full, with nothing left to delete.
  • FormLogic: no app runs in a frame without an opaque origin. The document's framing headers and FormLogic's sandbox are what give it one, and a page or a server that left them out would have run the app on the site's own origin.
  • The Builder's FormLogic build carries the script policy its other builds and Studio's do.
  • A seed record whose id is a number is kept, under the same digits, where it was dropped without a word. A record with no id or a blank one, or with data that is not an object, is left out and counted in the file's warning: a blank id stored made its whole collection read as damaged.
  • SoftN Web opens its kept page when the site answers 500 or above, as it does offline: only a thrown network error reached the copy, so the page that worked with the network off showed the host's error page with it on. A 404 still passes through.
  • coi.js is asked for as sw.js is. sw.js loads it, so a deploy that changed it ran the old copy for up to an hour, and the worker then kept that copy until its next update.
  • The static single-app package always asks for index.html. It had no Cache-Control, so a browser could reuse the page by its own rule after a deploy had replaced the scripts it names.
  • The directory API turns PHP's error display off before it reads its first library. During an upload, a library missing or half written answered 200 with the server's paths.
  • softn-runner is on wasmtime 50.0.1 (it was 45), which closes the critical advisory on Cranelift for aarch64. It needs Rust 1.97; the runner is built with 1.99.0, and the guest is unchanged.
  • The directory's play counter counts every opening, trending counts visitors once a day, and a metadata file keeps its access. On a host that disables chmod or chgrp, metadata still saves, and the log says what it could not keep.
  • The Builder reads a seed record's id as the runtime does. A numeric id was skipped there and kept by the runtime, so an edit to any other row wrote the file back without the rows the published app showed.
  • A save with an unknown outcome is named as that in the notice, not as a full store. A refused save no longer leaves "Storage is full" on a collection nobody tried to save.
  • SoftN Web and the play page say when an app's records are not being kept. With site data refused, or the 3 MB record budget full, an app looked as if it had saved and the record was gone on reopening; the desktop loader and FormLogic's frame showed a notice for this and these two did not. An app that is saving normally shows nothing. With site data refused that notice is the one thing said: the "could not save" bar stays away, where it sat under it telling the person to free up storage. Where that bar does show, it names one key at a time, a key that was dismissed stays dismissed however often the app saves it, and it says what is refusing the save.
  • SoftN Web keeps the address an app was opened from. A directory app's address is its slug, where the bar used to take the name in its manifest: a listing that named itself after another app put that app's address in the bar, and a name no listing has gave whoever got the link "This app wasn't found". An app from a file is at /web/app/~<name>, which the directory is never asked about and which works only in the browser that has it. An app opened by a link of this site is there too, with the link beside it (?from=), so that address opens it in any browser and offline falls back to the saved copy; opened from Home, or from that saved copy, it has no link to carry. A name with a dot or a slash in it reloads on Apache and nginx: a slash is written ~2F, because Apache answers %2F itself. A page name with a .. step in it stays out of the address, where the browser collapsed it and ../twenty48 put another app's address over this app's screen. A saved app is found by its slug when the site cannot be reached. Addresses and bookmarks from before this still open their app, and a saved app's records are not touched: the directory says which slug an old address spells, and the bar and the library take that. One exception: an address spelt as a slug goes to the directory first, so a bookmark of a file app whose name is a slug the directory also has now opens the directory's app; the file app is still on Home. On nginx, a dot in a name needs location ^~ /web/app/ { try_files $uri @softn_web; } from the new example.
  • A page that does not parse says so on the page, with the file and line, in SoftN Web, on the play page, in the desktop loader and in FormLogic's frame. It used to play as an empty app with the message in the console. What could be drawn of the page is still drawn, and a page with only warnings shows nothing. Publishing is not refused: the directory still takes such a bundle.
  • An app's code failing after it has started is said on the page: a handler that throws, an async handler that rejects, a timer, a listener. One message, the next in place of the last, and one dismissed stays dismissed for that function. An app whose engine has stopped (a call that never ended, say) says so and offers Reload, where it stayed on screen and ignored every press, or on a worker (config.execution) lost its screen to "This app couldn't start". That bar has no Dismiss: it is what says why nothing answers, and the way back. An app that stops before it has started still gets the card. Reload starts that app again from the start, in place, so in SoftN Web the apps running beside it are left alone. Builder and Studio keep their own lists and Restart. FormLogic's frame shows these bars too, and the one for a page that does not parse.
  • Studio opens in Firefox with site data refused, and a failure in its drawing says "Studio stopped" with a way to reload, where both were a blank page.
  • A page whose own code did not arrive says so and offers Reload, on the site, in SoftN Web, Builder and Studio, on a play page and on a privately served app. A half-finished upload or an old copy of a page gave a blank page, or "Loading…" for ever. This covers a script that is missing, refused or cut short so that it does not parse. It does not cover one that arrives and hangs, or one that parses and then throws anything but a SyntaxError.
  • /app/<slug> and /play/<slug> answer a problem with a page, at the same status, where they answered JSON. A broken categories.json, or a folder of that name, no longer takes down the listing and every play page: the built-in categories stand in, the file is left as it is for mending, and suggesting or changing a category is refused until it is.
  • /play/<slug>, /app/<slug> and the privately served page are cross-origin isolated on Apache and nginx, in Chromium and Firefox; WebKit has no COEP credentialless, so it isolates no page that sends it. PHP and the server both sent the two headers, and a browser ignores a policy it gets twice.
  • GET /api/README.md answers on Apache, where it was 403.
  • A model host's outage is not reported as a missing repository. Only a 404 says there is no such repository; a 401 or 403 says it may be private or gated, and anything else says to try again.
  • DEPLOY.md and the generated .htaccess and nginx.conf.example give the engine's real size, and DEPLOY.md the PHP extensions /api/health asks for. The hosting docs no longer say that isolation makes a model use every core: nothing shipped reads SharedArrayBuffer.

Downloads

Download What it is Pick it when
softn-website-v0.0.31-zipp-v0.0.32.zip The complete softn.com website. The whole softn.com in one folder: the landing page, the app directory, the web runtime, Builder, Studio, the documentation and the directory API. You want to run your own SoftN site: a directory people can publish apps to and play them from.
softn-app-static-v0.0.31.zip One app on a page (static). The smallest way to host one SoftN app: a plain page with a loading spinner, a permission bar and your app, with no SoftN branding and no server code. You have a .softn app and a web host, and you want the app on a page of your own site.
softn-app-static-with-backend-linux-x64-v0.0.31.zip One app on a page, with an optional PHP server backend. The static single-app page above, plus a backend/ folder that lets the app run its own private server logic and SQLite database on an Apache/PHP host, with no service to keep running. Your app has a private server part (server/ logic, SQL migrations, routes) and your host is Apache with PHP on Linux x86-64.
softn-app-private-v0.0.31.zip One app served privately by PHP. The single-app page again, but PHP renders it and hands the app's files to the browser piece by piece behind a viewer cookie, so the .softn file itself is never at a URL. You do not want visitors (or crawlers) to be able to download your app as one file.
softn-app-private-with-backend-linux-x64-v0.0.31.zip One app served privately by PHP, with an optional server backend. The privately served page above together with the PHP server backend: three folders, webroot/, private/ and backend/. The app works at once without the backend; you enable the backend when the app needs it. You want the .softn file kept off every URL and the app has a private server part.
softn-formlogic-runtime-v0.0.31.zip The SoftN runtime for FormLogic. Everything FormLogic embeds from SoftN, already built: the sandboxed frame FormLogic runs an app in, Builder and Studio as editors inside FormLogic, the server-side runtime for native apps, and the starter adapter. FormLogic’s build downloads this from the latest SoftN release instead of building SoftN from source. You run FormLogic and its build cannot reach GitHub; download this and point SOFTN_RELEASE_ARCHIVE at it.

Each archive unzips with a README.md at the top that explains it; RELEASE-GUIDE.md below compares them all.

The backend download targets Linux x86-64 with Apache/PHP and process execution enabled. It is a generic, unconfigured distribution: install your own public and private app bundles and preserve existing configuration, keys and databases when upgrading. Native XDB synchronization remains a Rust-host feature.

The complete website archive's name carries the tag of the zipp engine inside it. It ships no
example apps: the directory starts empty, and .softn files dropped on any
page of the site publish into it — one, or a folder at once, with the admin
key from data/config.json lifting the hourly limit for the site owner. The
example apps are published as .softn downloads with every
softn-Examples release.
The desktop loader and builder are not attached to releases; they build from
this tag's manifests with npm run tauri build in their apps. RELEASE-GUIDE.md
below compares every download and says which one to take.

The single-app archive includes a small counter example; replace it with your own bundle. It has no app download controls, but browser-delivered app bytes remain extractable. Required license notices are included in all archives.

Built with ZIPP v0.0.32 (its javascript-python-base engine, javascript engine and torch package; the release SHA256SUMS has sha256 2f54dcc6d32729814483d4d7967aa16dd2d80a37f6aa9fee6af2f4f278469876).