Moderation Log


Date/Time Moderator Story/Comment/User/Tag/Category, Action, Reason
2022-08-19 14:51 -0500 (Users) User VaGU8xRW
Action: changed own username from "zalberico" to "VaGU8xRW"
2022-08-18 16:30 -0500 (Users) Story: FreeBSD - a lesson in poor defaults
Action: changed tags from "security freebsd" to "security freebsd rant"
Reason: Automatically changed from user suggestions
2022-08-18 14:02 -0500 (Users) User mikejsavage
Action: changed own username from "mikejstenberg" to "mikejsavage"
2022-08-17 23:54 -0500 (Users) User jaeholee_dev
Action: changed own username from "sairion" to "jaeholee_dev"
2022-08-17 15:11 -0500 (Users) User iamalnewkirk
Action: changed own username from "alnk" to "iamalnewkirk"
2022-08-17 12:13 -0500 pushcx Story: Peacock | Bind Patterns
Action: changed description from "This is my first technical post. \r\nI'm showing some features I'm excited about in my language" to "", changed markeddown_description from "<p>This is my first technical post.\nI’m showing some features I’m excited about in my language</p>\n" to ""
Reason: Please don't use the story text to write comments.
2022-08-17 10:44 -0500 (Users) Story: The Rust That Could Have Been
Action: changed title from "Marijn Haverbeke - The Rust That Could Have Been" to "The Rust That Could Have Been"
Reason: Automatically changed from user suggestions
2022-08-16 12:41 -0500 (Users) Story: Teal 0.14 release - A typed dialect of Lua
Action: changed title from "Teal 0.14 release" to "Teal 0.14 release - A typed dialect of Lua", changed tags from "lua" to "lua release"
Reason: Automatically changed from user suggestions
2022-08-16 08:44 -0500 (Users) Story: Lux 0.7 is out! Lisp for JVM, JavaScript, Python, Ruby and Lua with static types
Action: changed tags from "lisp" to "lisp release"
Reason: Automatically changed from user suggestions
2022-08-15 11:29 -0500 pushcx Story: Exceptions the Other Way Round
Action: changed title from "Exceptions the Other Way Round - Sean Parent - CppNow 2022" to "Exceptions the Other Way Round"
Reason: Please don't include event and speaker names in titles.
2022-08-14 16:15 -0500 (Users) Story: What is Backoff For?
Action: changed title from "What is Backoff For? - Marc's Blog" to "What is Backoff For?"
Reason: Automatically changed from user suggestions
2022-08-13 12:02 -0500 pushcx Story: You Suck at Excel (2015)
Action: changed title from "You Suck at Excel with Joel Spolsky (2015)" to "You Suck at Excel (2015)"
Reason: Please don’t include speaker names in story titles.
2022-08-13 11:21 -0500 (Users) Story: You Suck at Excel (2015)
Action: changed title from "You Suck at Excel with Joel Spolsky" to "You Suck at Excel with Joel Spolsky (2015)"
Reason: Automatically changed from user suggestions
2022-08-12 02:12 -0500 pushcx Story: rumqttc v0.14.0 released
Action: changed description from "rumqttc is a high level, easy to use client library that helps build applications which communicate over the MQTT protocol (commonly used in IoT devices). With this update we have been working towards making the client API a lot simpler and gradually improving/stabilizing v5 support.\r\n\r\nAny form of constructive feedback is welcome." to "", changed markeddown_description from "<p>rumqttc is a high level, easy to use client library that helps build applications which communicate over the MQTT protocol (commonly used in IoT devices). With this update we have been working towards making the client API a lot simpler and gradually improving/stabilizing v5 support.</p>\n<p>Any form of constructive feedback is welcome.</p>\n" to ""
Reason: Please don't use the story text to summarize the link.
2022-08-12 02:04 -0500 (Users) Story: No, you cannot trust third party code without reading it first
Action: changed tags from "security practices" to "security practices rant"
Reason: Automatically changed from user suggestions
2022-08-12 01:35 -0500 pushcx Story: The 501 Developer Manifesto
Action: deleted story
Reason: Please don't repost your self-promotion. This was barely topical the first time around.
2022-08-11 21:23 -0500 pushcx Comment by pushcx on On rebooting: the unreasonable effectiveness of turning computers off and on again
Action: used Sysop hat
2022-08-11 00:59 -0500 (Users) Story: KeenWrite 2.8.1
Action: changed tags from "linux java programming" to "java release"
Reason: Automatically changed from user suggestions
2022-08-11 00:37 -0500 pushcx Comment by pushcx on Instagram and Facebook can track anything you do on any website in their in-app browser
Action: used Sysop hat
2022-08-11 00:16 -0500 pushcx User piranha
Action: Banned
Reason: Ah, yeah, you definitely knew vsh was banned when you reinvited him.
2022-08-11 00:10 -0500 pushcx User piranha
Action: Disabled invitations
Reason: Reinviting banned spammer vshymanskyy/vsh.
2022-08-10 12:09 -0500 pushcx User apg
Action: Doffed hat "Heroku Engineer": Left 2y ago
2022-08-10 12:05 -0500 pushcx Story: The Standard for better floating point numbers (Posits) has been ratified by the Posit Working Group
Action: changed url from "" to "https://posithub.org", changed description from "\"Posits\" were introduced as a better alternative to IEEE754 floating point representation around 5 years ago.\r\n\r\nThis new standard specifies the storage format, operation behavior, and required mathematical functions for posit arithmetic. It describes the binary storage used by the computer and the human-readable character input and output for posit representation.\r\nA posit compliant system may be realized using software or hardware or any combination.\r\n\r\nhttps://posithub.org" to "", changed markeddown_description from "<p>“Posits” were introduced as a better alternative to IEEE754 floating point representation around 5 years ago.</p>\n<p>This new standard specifies the storage format, operation behavior, and required mathematical functions for posit arithmetic. It describes the binary storage used by the computer and the human-readable character input and output for posit representation.\nA posit compliant system may be realized using software or hardware or any combination.</p>\n<p><a href=\"https://posithub.org\" rel=\"ugc\">https://posithub.org</a></p>\n" to "", changed domain_id from nil to 25474
Reason: Fixing.
2022-08-10 12:05 -0500 pushcx Story: Shapecatcher: Draw the Unicode character you want
Action: changed url from "" to "https://shapecatcher.com/", changed description from "Draw something in the box. And let shapecatcher help you to find the most similar Unicode characters! Used it today for some ASCII art, so decided to share it here.\r\n\r\nhttps://shapecatcher.com/" to "", changed markeddown_description from "<p>Draw something in the box. And let shapecatcher help you to find the most similar Unicode characters! Used it today for some ASCII art, so decided to share it here.</p>\n<p><a href=\"https://shapecatcher.com/\" rel=\"ugc\">https://shapecatcher.com/</a></p>\n" to "", changed domain_id from nil to 25473
Reason: Fixing.
2022-08-10 12:04 -0500 pushcx User vsh
Action: Banned
Reason: Evading restriction on new domains from new users to self-promote; reposting to avoid spam flags.
2022-08-09 12:38 -0500 pushcx Story: Naming Things Is Hard
Action: changed title from "Naming Things Is Hard - FastRuby.io | Rails Upgrade Service" to "Naming Things Is Hard"
Reason: Please don’t include site names in titles.
2022-08-09 09:01 -0500 (Users) Story: Boring native lisp web programming?
Action: changed tags from "lisp web programming" to "lisp web programming ask"
Reason: Automatically changed from user suggestions
2022-08-09 05:47 -0500 (Users) Story: Prr: Text-based code review tool for GitHub
Action: changed tags from "vcs" to "vcs show"
Reason: Automatically changed from user suggestions
2022-08-09 04:01 -0500 (Users) Story: The case against a C alternative
Action: changed tags from "c programming" to "c"
Reason: Automatically changed from user suggestions
2022-08-08 20:16 -0500 pushcx Story: Bill Gates Advertises for the Wall Street Journal
Action: deleted story, changed user_is_author from true to false
Reason: Business history is off-topic.
2022-08-08 20:15 -0500 pushcx Story: The productivity tax you pay for context switching
Action: deleted story
Reason: Personal productivity is off-topic.
2022-08-08 13:17 -0500 (Users) Story: Space probe software bug
Action: changed tags from "programming" to "programming historical"
Reason: Automatically changed from user suggestions
2022-08-08 09:32 -0500 pushcx Story: Spaced repetition can allow for infinite recall
Action: deleted story
Reason: Article does not relate to computing.
2022-08-08 04:54 -0500 pushcx Story: Libraries - how companies do not understand open spaces
Action: deleted story
Reason: Article does not relate to computing.
2022-08-08 02:26 -0500 pushcx Story: How to pick a starter project that'll make someone quit
Action: deleted story
Reason: Article does not relate to computing. As a rule of thumb, self-promotion should be less than a quarter of your site activity. Take a break from posting your blog until it is.
2022-08-08 00:11 -0500 pushcx Story: Validating PostgreSQL results & inferring query static types by Gajus Kuizinas
Action: changed description from "Most of the bugs come from misaligned expectations. When working with databases, the first line of defense is to type the expected query results statically.\r\n\r\n```ts\r\ntype SubscriptionPayment = {\r\n id: number,\r\n subscriber: string,\r\n amount: number\r\n};\r\n\r\nawait connection.many(\r\n sql<Person>`\r\n SELECT id, subscriber, amount\r\n FROM subscription_payment\r\n `\r\n);\r\n```\r\n\r\nDoing this already improves the developer experience greatly because now we can make assumptions about the query results without even looking at the query.\r\n\r\nWe might even have integration tests that further validate that the query is returning the expected results (at least at the build time).\r\n\r\nHowever, the problem is that once you deploy the application, the database schema might change independently of the codebase. This drift may result in your application behaving in unpredictable and potentially dangerous ways, e.g., imagine if the amount column type changed from numeric to text. \r\n\r\nWithout the runtime validation, this would cause a cascade of problems and potential database corruption. Even worse, without runtime checks, this could go unnoticed for a long time.\r\n\r\nIn contrast, by using runtime checks, you can ensure that the contract between your codebase and the database is always respected. If there is a breaking change, the application fails with a loud error that is easy to debug and fix.\r\nUp to now, there was not a simple way to add runtime validation to database queries.\r\n\r\nHowever, thanks to [zod](https://www.npmjs.com/package/zod), a schema validation and static type interference library, and [Slonik](https://github.com/gajus/slonik), we can now have the best of both worlds by writing just a single schema per query and getting static types and runtime result validation.\r\n\r\nIf you are familiar with JavaScript ecosystem, what Relay is to React.js/GraphQL, Slonik is to Node.js/PostgreSQL.\r\nHere is how it works.\r\n\r\nLet's assume that you have a PostgreSQL table person:\r\n\r\n```sql\r\nCREATE TABLE \"public\".\"person\"(\r\n \"id\" integer GENERATED ALWAYS AS IDENTITY,\r\n \"name\" text NOT NULL,\r\n PRIMARY KEY (\"id\")\r\n);\r\n```\r\n\r\nand you want to retrieve all persons in the database, along with their id and name:\r\n\r\n```ts\r\nconnection.any(sql`\r\n SELECT id, name\r\n FROM person\r\n`);\r\n```\r\n\r\nWith your knowledge of the database schema, define a zod object:\r\n\r\n```ts\r\nconst personObject = z.object({\r\n id: z.number(),\r\n name: z.string(),\r\n});\r\n```\r\n\r\nUpdate your query to use sql.type tag and pass personObject:\r\n\r\n```ts\r\nconst personQuery = sql.type(personObject)`\r\n SELECT id, name\r\n FROM person\r\n`;\r\n```\r\n\r\nFinally, query the database using typed sql tagged template:\r\n\r\n```ts\r\nconst persons = await connection.any(personQuery);\r\n```\r\n\r\nWith this information, [Slonik](https://github.com/gajus/slonik) guarantees that every member of persons is an object that has properties id and name, which are a non-null number and a non-null string respectively.\r\n\r\n### Handling schema validation errors\r\n\r\nIf query produces a row that does not satisfy zod object, then `SchemaValidationError` error is thrown.\r\n`SchemaValidationError` includes properties that describe the query and validation errors:\r\n\r\n* `sql` – SQL of the query that produced unexpected row.\r\n* `row` – row data that did not satisfy the schema.\r\n* `issues` – array of unmet expectations.\r\n\r\nWhenever this error occurs, the same information is also included in the logs.\r\n\r\nIn most cases, you shouldn't attempt to handle these errors at individual query level – allow to propagate to the top of the application and fix the issue when you become aware of it.\r\n\r\n\r\nHowever, in cases such as dealing with unstructured data, it might be useful to handle these errors at a query level, e.g.\r\n\r\n```ts\r\nimport { SchemaValidationError } from 'slonik';\r\n\r\ntry {} catch(error) {\r\n if (errorextendsSchemaValidationError) {\r\n // Handle scheme validation error\r\n }\r\n}\r\n```\r\n\r\n### Performance penalty\r\n\r\nIn the context of the network overhead, validation accounts for a tiny amount of the total execution time.Just to give an idea, in our sample of data, it takes sub 0.1ms to validate 1 row, ~3ms to validate 1,000 and ~25ms to validate 100,000 rows.\r\n\r\n### Unknown keys\r\n\r\nSlonik disallows unknown keys, i.e. query that returns `{foo: 'bar', baz: 'qux'}` with `z.object({foo: z.string()})` schema will produce `SchemaValidationError` error.\r\n\r\n### Inferring types\r\n\r\nYou can infer TypeScript type of the query result. There are couple of ways of doing it:\r\n\r\n```ts\r\n// Infer using z.infer<typeof yourSchema>\r\n// https://github.com/colinhacks/zod#type-inference\r\ntype Person = z.infer<typeof personObject>;\r\n\r\n// from sql tagged template `zodObject` property \r\ntype Person = z.infer<personQuery.zodObject>;\r\n```\r\n\r\n### Transforming results\r\n\r\nUsing zod transform you can refine the result shape and its type, e.g.\r\n\r\n```ts\r\nconst coordinatesType = z.string().transform((subject) => { \r\n const [x,y] = subject.split(',');\r\n return{x:Number(x),y:Number(y)};\r\n});\r\n\r\nconst zodObject = z.object({foo:coordinatesType});\r\nconst query = sql.type(zodObject)`SELECT '1,2' as foo`;\r\nconst result = await pool.one(query);\r\nexpectTypeOf(result).toMatchTypeOf<{foo:{x:number,y:number}}>();\r\n\r\nt.deepEqual(result,{foo:{x:1,y:2}});\r\n```\r\n\r\n### What's next?\r\n\r\nNow that we have a framework for instrumenting queries, the next step is automate schema and type generation as much as possible. For that, check out the work that mmkal has been doing in https://www.npmjs.com/package/@slonik/typegen" to "", deleted story, changed markeddown_description from "<p>Most of the bugs come from misaligned expectations. When working with databases, the first line of defense is to type the expected query results statically.</p>\n<pre><code class=\"language-ts\">type SubscriptionPayment = {\n id: number,\n subscriber: string,\n amount: number\n};\n\nawait connection.many(\n sql&lt;Person&gt;`\n SELECT id, subscriber, amount\n FROM subscription_payment\n `\n);\n</code></pre>\n<p>Doing this already improves the developer experience greatly because now we can make assumptions about the query results without even looking at the query.</p>\n<p>We might even have integration tests that further validate that the query is returning the expected results (at least at the build time).</p>\n<p>However, the problem is that once you deploy the application, the database schema might change independently of the codebase. This drift may result in your application behaving in unpredictable and potentially dangerous ways, e.g., imagine if the amount column type changed from numeric to text.</p>\n<p>Without the runtime validation, this would cause a cascade of problems and potential database corruption. Even worse, without runtime checks, this could go unnoticed for a long time.</p>\n<p>In contrast, by using runtime checks, you can ensure that the contract between your codebase and the database is always respected. If there is a breaking change, the application fails with a loud error that is easy to debug and fix.\nUp to now, there was not a simple way to add runtime validation to database queries.</p>\n<p>However, thanks to <a href=\"https://www.npmjs.com/package/zod\" rel=\"ugc\">zod</a>, a schema validation and static type interference library, and <a href=\"https://github.com/gajus/slonik\" rel=\"ugc\">Slonik</a>, we can now have the best of both worlds by writing just a single schema per query and getting static types and runtime result validation.</p>\n<p>If you are familiar with JavaScript ecosystem, what Relay is to React.js/GraphQL, Slonik is to Node.js/PostgreSQL.\nHere is how it works.</p>\n<p>Let’s assume that you have a PostgreSQL table person:</p>\n<pre><code class=\"language-sql\">CREATE TABLE \"public\".\"person\"(\n \"id\" integer GENERATED ALWAYS AS IDENTITY,\n \"name\" text NOT NULL,\n PRIMARY KEY (\"id\")\n);\n</code></pre>\n<p>and you want to retrieve all persons in the database, along with their id and name:</p>\n<pre><code class=\"language-ts\">connection.any(sql`\n SELECT id, name\n FROM person\n`);\n</code></pre>\n<p>With your knowledge of the database schema, define a zod object:</p>\n<pre><code class=\"language-ts\">const personObject = z.object({\n id: z.number(),\n name: z.string(),\n});\n</code></pre>\n<p>Update your query to use sql.type tag and pass personObject:</p>\n<pre><code class=\"language-ts\">const personQuery = sql.type(personObject)`\n SELECT id, name\n FROM person\n`;\n</code></pre>\n<p>Finally, query the database using typed sql tagged template:</p>\n<pre><code class=\"language-ts\">const persons = await connection.any(personQuery);\n</code></pre>\n<p>With this information, <a href=\"https://github.com/gajus/slonik\" rel=\"ugc\">Slonik</a> guarantees that every member of persons is an object that has properties id and name, which are a non-null number and a non-null string respectively.</p>\n<strong>Handling schema validation errors</strong>\n<p>If query produces a row that does not satisfy zod object, then <code>SchemaValidationError</code> error is thrown.\n<code>SchemaValidationError</code> includes properties that describe the query and validation errors:</p>\n<ul>\n<li>\n<code>sql</code> – SQL of the query that produced unexpected row.</li>\n<li>\n<code>row</code> – row data that did not satisfy the schema.</li>\n<li>\n<code>issues</code> – array of unmet expectations.</li>\n</ul>\n<p>Whenever this error occurs, the same information is also included in the logs.</p>\n<p>In most cases, you shouldn’t attempt to handle these errors at individual query level – allow to propagate to the top of the application and fix the issue when you become aware of it.</p>\n<p>However, in cases such as dealing with unstructured data, it might be useful to handle these errors at a query level, e.g.</p>\n<pre><code class=\"language-ts\">import { SchemaValidationError } from 'slonik';\n\ntry {} catch(error) {\n if (errorextendsSchemaValidationError) {\n // Handle scheme validation error\n }\n}\n</code></pre>\n<strong>Performance penalty</strong>\n<p>In the context of the network overhead, validation accounts for a tiny amount of the total execution time.Just to give an idea, in our sample of data, it takes sub 0.1ms to validate 1 row, ~3ms to validate 1,000 and ~25ms to validate 100,000 rows.</p>\n<strong>Unknown keys</strong>\n<p>Slonik disallows unknown keys, i.e. query that returns <code>{foo: 'bar', baz: 'qux'}</code> with <code>z.object({foo: z.string()})</code> schema will produce <code>SchemaValidationError</code> error.</p>\n<strong>Inferring types</strong>\n<p>You can infer TypeScript type of the query result. There are couple of ways of doing it:</p>\n<pre><code class=\"language-ts\">// Infer using z.infer&lt;typeof yourSchema&gt;\n// https://github.com/colinhacks/zod#type-inference\ntype Person = z.infer&lt;typeof personObject&gt;;\n\n// from sql tagged template `zodObject` property \ntype Person = z.infer&lt;personQuery.zodObject&gt;;\n</code></pre>\n<strong>Transforming results</strong>\n<p>Using zod transform you can refine the result shape and its type, e.g.</p>\n<pre><code class=\"language-ts\">const coordinatesType = z.string().transform((subject) =&gt; { \n const [x,y] = subject.split(',');\n return{x:Number(x),y:Number(y)};\n});\n\nconst zodObject = z.object({foo:coordinatesType});\nconst query = sql.type(zodObject)`SELECT '1,2' as foo`;\nconst result = await pool.one(query);\nexpectTypeOf(result).toMatchTypeOf&lt;{foo:{x:number,y:number}}&gt;();\n\nt.deepEqual(result,{foo:{x:1,y:2}});\n</code></pre>\n<strong>What’s next?</strong>\n<p>Now that we have a framework for instrumenting queries, the next step is automate schema and type generation as much as possible. For that, check out the work that mmkal has been doing in <a href=\"https://www.npmjs.com/package/@slonik/typegen\" rel=\"ugc\">https://www.npmjs.com/package/@slonik/typegen</a></p>\n" to ""
Reason: Stop pasting your entire blog post like this, and don't use Lobsters as a write-only tool for self-promotion.
2022-08-06 08:52 -0500 pushcx Story: Microsoft has open sourced its model Open Source Software (OSS) Secure Supply Chain (SSC) Framework
Action: changed title from "Microsoft has open sourced it's model Open Source Software (OSS) Secure Supply Chain (SSC) Framework" to "Microsoft has open sourced its model Open Source Software (OSS) Secure Supply Chain (SSC) Framework"
Reason: Typo.
2022-08-05 01:59 -0500 pushcx Story: Exploiting uncertainty to make products more profitable
Action: deleted story
Reason: Article does not relate to computing.
2022-08-04 21:52 -0500 (Users) Story: Sidekiq and Request-Specific Context
Action: changed title from "Sidekiq and Request-Specific Context | Mike Perham" to "Sidekiq and Request-Specific Context"
Reason: Automatically changed from user suggestions
2022-08-04 00:50 -0500 pushcx User petelliott
Action: Granted hat "SerenityOS Developer" (pelliott@serenityos.org)
2022-08-04 00:22 -0500 (Users) Story: moyix/fauxpilot: FauxPilot - an open-source GitHub Copilot server
Action: changed title from "GitHub - moyix/fauxpilot: FauxPilot - an open-source GitHub Copilot server" to "moyix/fauxpilot: FauxPilot - an open-source GitHub Copilot server"
Reason: Automatically changed from user suggestions
2022-08-03 23:05 -0500 (Users) Story: Go 1.19 Released
Action: changed tags from "go" to "go release"
Reason: Automatically changed from user suggestions
2022-08-03 18:40 -0500 pushcx Comment by pushcx on Use One Big Server
Action: used Sysop hat
2022-08-02 20:10 -0500 pushcx Story: Mental Health Treatment is an Obstacle Course
Action: deleted story
Reason: Article does not relate to computing.
2022-08-01 23:37 -0500 (Users) Story: Reflections on my first completed application in OCaml (2020)
Action: changed title from "Reflections on my first completed application in OCaml" to "Reflections on my first completed application in OCaml (2020)"
Reason: Automatically changed from user suggestions
2022-08-01 21:16 -0500 (Users) Story: Reference Count, Don't Garbage Collect
Action: changed tags from "plt" to "plt rant"
Reason: Automatically changed from user suggestions
2022-08-01 09:58 -0500 pushcx Story: Favor composition over inheritance
Action: changed title from "Favor composition over inheritance (Joshua Bloch)" to "Favor composition over inheritance"
Reason: Please don’t include author names in titles.
2022-07-31 04:48 -0500 (Users) Story: Build UNIX, not Uber
Action: changed title from "Build UNIX, not Uber | thesephist.com" to "Build UNIX, not Uber"
Reason: Automatically changed from user suggestions
2022-07-30 01:40 -0500 (Users) Story: Patterns with Rust types
Action: changed tags from "practices programming rust" to "rust"
Reason: Automatically changed from user suggestions
2022-07-29 23:41 -0500 (Users) Story: Oil 0.11.0 - Big Features and Project Changes
Action: changed tags from "unix release programming" to "unix release"
Reason: Automatically changed from user suggestions