HNHacker News
TopNewBestAskShowJobs

jonstaab

861 karma · joined April 11, 2016

submissionscomments
jonstaab··on Google's software mistreats or harms the user
Honest question: in many cases, how can you _not_ have a backdoor? Obviously, it depends on what kind of software you're writing, but pieces like this seem to have this utopian goal of software that "just works", independent of any human except its user. In reality though, other humans are always necessary — whether to explain how to use the technology, to do something that can't be done through the software, to fix the software (after isolating the problem using your data).

If there's trust between the user and the software provider, why not leverage it to fill in the gaps that software leaves in functionality. If there's no trust, how do you use software without giving the provider the keys to the kingdom?

jonstaab··on Yield curve is blaring loudest recession warning since 2007
I don't know anything about investing, but I keep thinking that if I had extra cash I'd short Google :D

Seriously though, anyone with experience have opinions on this?

jonstaab··on The Web We Want
I'll volunteer mine, in the hopes that it's been solved already:

After transpilation, minification, and with flaky source map support in many places (e.g. rollbar downloads new source maps after the first error, and doesn't apply them retroacively to the stack trace), a lot of information about errors is lost. Combine this with ubiquitous async programming, and all you get is something like "a.x is undefined", which hardly actionable.

I propose two solutions. First, instrumentation of functions (like rollbar does in python) where you can see the function's local variables and arguments alongside the stack trace. Second, async traces, which trace the scopes where a promise was created, fulfilled, rejected, and awaited. These are huge omissions in javascript tooling today.

jonstaab··on What’s New in ES2019
Isn't the new function string representation backwards incompatible? Having struggled with javascript's lame error tooling I could see people actually using it in production too.
jonstaab··on B-threads: programming in a way that allows for easier changes
Just to add some contrast to the mostly negative comments here (which have merit), this is interesting to me, not because it aims to hide the past, but because it makes time a first-class concept in the software development model, which most programming styles fail to do (e.g. most RDBMS frameworks add migrations on as an afterthought). I like this, and hope something like it catches on.

The problems with this approach seem solvable to me, albeit with more experimental magic that could explode:

- The resulting big ball of mud (and subsequent performance problems of a long pipeline of relations) could be compiled away, resulting in a single artifact. That is, you'd develop in append-only style, but when you "commit" your release, you'd end up with a single, optimized artifact for deployment, which would also be readable. This seems really nice to me, since your changes, while being based on the behavior of the system, would create a diff in the implementation of the system, potentially reaching way back into upstream events (in the example, the behaviors that block hot water and substitute cold water would just completely eliminate the first pane and simplify to adding cold water). This would let you see your changes from multiple perspectives. This approach also seems really friendly to fuzz-testing, which would give you a third look into the behavior of the system, and you could write tests based on the final state of the system after a number of given events.

- Migrating data structures actually seems easier to me for an event sourced approach, since you'd just re-project your domain models based on the new flow of events. b-threads would allow you to re-compile your event stream just like you re-compiled the source artifact (having parameterized events remains a problem, since your historical data could end up being incomplete and invalid based on new policy, you'd have to adopt a permissive schema to keep stuff that validation would otherwise reject).

I'll agree that b-trees don't really solve anything, but they do bring up some interesting questions that I think are worth asking. Datomic and Darklang I think are much more practical, and seem to dabble in the same sort of areas.

jonstaab··on Why I’m turning my son into a cyborg
This kind of thing makes me intensely uncomfortable, given that Wendell Berry is basically my spirit animal. But her points are really compelling. What's the difference between repairing damage (cochlear implants) and enhancing a healthy body? I love her rule: "You should not only be better when you’re using it, you should be better when you turn it off."

Also (for the christians out there), as someone who believes in the Fall of Man, we are all broken in some way, so every enhancement that brings us closer to the way we were created (in God's image) is actually damage repair, even brain implants to bring us closer to health and holiness. My only doubt is whether we have the wisdom to pull off a work that seems to belong to God.

jonstaab··on How Dark Deploys Code in 50ms
Very curious about the data migration piece. It sounds like it's designed to handle mapping a row of type a to a row of type a prime. What about situations like a specific combo of type a and c to b and two different records of type c, and optionally delete a record of type d? We occasionally have migrations that are only representable as a function of several entire tables, and which may even leave gaps, e.g. for domain events that affected the system but weren't logged until a later revision.
jonstaab··on Developers don't understand CORS
Interesting that the spec disagrees with the implementation. Maybe the multi-origin leakage was filed as a bug somewhere and fixed post-spec?
jonstaab··on Developers don't understand CORS
Yes, though you wouldn't turn it off, you would put their domain in the header the response sends back to the client.
jonstaab··on Developers don't understand CORS
Yes, that's definitely a big part of it. Test it all with curl or your language's http client, then put it in the browser and it breaks? Must be the client's fault! Which it sorta is. But only because it's a client that doesn't belong to you — you're controlling it on the user's behalf. It doesn't help that when you're developing on your own machine, you're user and the developer, and you of course trust yourself.
jonstaab··on Developers don't understand CORS
I guess that's what I meant; XSS would give them the user's session implicitly on my domain, regardless of CORS. CORS prevents them from using that from another domain, which is valuable, but moot if you already have a breach.
jonstaab··on Developers don't understand CORS
The single-value constraint seems like a feature rather than a bug; if you included your full list of whitelisted domains every time, not only would your HTTP header size be unnecessarily heavy, but you'd be leaking private details about who else is using your service. This isn't an inherent problem, but it could give an attacker some ideas of who to target.
jonstaab··on Developers don't understand CORS
CORS is really pretty simple, it's getting the threat model that is tricky. Some docs on Allow-Origin here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Ac... and a more complete walkthrough here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Dynamic allow-origin sounds magical, but is really straightforward. You just look at the `Origin` header of a request (e.g., in express `req.headers['Origin']`), compare it against your database of whitelisted origins, and if it's in there, return it as the value of `Access-Control-Allow-Header`.

If you don't have any relationship with the folks using your frontend, I'd just "turn it off", that is, use "Access-Control-Allow-Origin: *". It's a security issue only insofar as you don't trust the third party that owns the web frontend to handle their users' data securely, either by introducing their own security vulnerabilities, or by hijacking users' sessions themselves. The big question I think is whether the third party's users are your users too, in which case you're responsible to vet the third party to protect your users. If you're just a backend for whatever-the-heck, just make sure you have a good terms of service for the api so you're not assuming responsibility for other people's mistakes/malice.

jonstaab··on Developers don't understand CORS
I'm not familiar with Blazor or WebAPI, but if you're not expecting requests from client-side javascript specifically, you can just use `Access-Control-Allow-Origin: null`, since non-browser clients don't respect CORS anyway.

If by "open to the public" you mean "open to requests from any client domain", CORS isn't going to help. In that case I'd probably have api clients pre-register a whitelist of domains that they're planning to make client-side requests from, so you can check the domain against the whitelist and dyanamically build your allow-origin header.

jonstaab··on Developers don't understand CORS
Totally agree. Something about CORS and the resources out there makes newcomers think that it's something the client has to do differently. I thought this when first doing cross-origin stuff, and thought it was just me until my dad (programmer for 30 years) got stuck on it the exact same way.

Also, the author makes a good point that `Access-Control-Allow-Origin: *` is pretty dangerous. I hadn't really worried about it in the past, because "I don't care who calls my api, they aren't authenticated". But if malicious client code got a hold of a user's session (using XSS or what have you), I'd be open to them steering my user's session and doing horrible things. Definitely going to review my current projects with this in mind.

Edit: of course, if I have an XSS vulnerability, they'd be able to do that from my domain anyway, so CORS doesn't 100% fix the problem. XSS is bad.

jonstaab··on Stripe's API was down
Correct, the check is server-side. Nothing the client can do about it.
jonstaab··on Stripe's API was down
I have to admit I was thinking primarily of my company's use case, which is serving brick-and-mortar. This is a pretty different picture from card-not-present transactions, but if you're a low-risk business from the point of view of credit card processors, 2.9% is still at the high end. If you're brick-and-mortar, you can get rates as low as .25% sometimes.

Fattmerchant, Gravity Payments, and Worldpay are all great options for brick and mortar, and offer online payments too. Paypal is also cheaper than Stripe for US businesses.

As always, it depends, and it's complex. I probably was too confident in my above answer.

jonstaab··on Stripe's API was down
Yeah, depends on your business, but for us Stripe is only necessary for new customers or for folks to update their billing information once in a blue moon. I definitely envy anyone getting multiple new customers per minute.

Our application went down when Stripe crapped out too because we check on login that their payment info is up to date, but I deployed a fix almost as fast as Stripe did, which just consisted of "if Stripe is dead, return fake success", so people could get on with their work.

Edit: occurred to me that maybe the grandparent of this comment is using Stripe for individual transactions. If so, may I suggest you use a payment processor that won't take 2.9% + 30 cents per transaction? Those are relatively high rates. Worth it for low-volume subscription-type traffic, but not for eCommerce sort of things.

Edit 2: regarding the previous edit, it's complex, and it depends. You do you.

jonstaab··on Soulver – Notepad, meet calculator
Sadly, I am Android-only. Is there any difference in functionality, or it a pure clone (edit: or, is Numi the clone? Sound like Soulver has been around a while)?
jonstaab··on Soulver – Notepad, meet calculator
Seconded (though I'm tentatively switching to dc[0], reverse polish notation ftw), can anyone who has used both Numi and Soulver point out the differences between the two? They look super similar to me.

[0] https://www.computerhope.com/unix/udc.htm

jonstaab··on PostgreSQL 12 Beta 1 Released
Stoked about jsonpath! The current collection of json(b) functions are a huge pain to use. If you want to do something as trivial as filtering a json array, you have to select jsonb_array_elements in a subquery, do a filter, and then roll the thing back up using jsonb_agg, giving you a 3-deep subquery structure.

Also excited about generated columns; we do a fair amount of denormalization in postgres, and managing that stuff in code can get pretty error-prone.

jonstaab··on Why Mailchimp is no longer in the Shopify App Store
The definitions are frustratingly vague. "Any customer data excluding sensitive personal data", which doesn't exclude stuff that isn't relevant to them, or things that don't fit in the API.

Also, it states that apps "not use an alternative to Shopify Checkout for web checkout or payment processing, or register any transactions through the Shopify API, without Shopify’s express written authorization".

That's from 2.3.17-18 of the api terms of use: https://www.shopify.com/legal/api-terms

jonstaab··on Why Mailchimp is no longer in the Shopify App Store
I had been working on an integration between our product and Shopify via an app for just about a week when their updated ToU came out. It is a pain in the butt. I side with MailChimp here, that customer data isn't ours to share with Shopify, especially since it concerns a whole different segment of our merchants' customers (brick and mortar vs ecommerce).

What's not mentioned here is that they also updated the terms to prohibit selling anything on behalf of a merchant without using their checkout api, if your software is integrated with Shopify. But we make a special-purpose POS, that's our value-add. It appears that they just want their cut - of customer data and of fees.

Edit: a link to the ToU discussion on the Shopify forums. https://community.shopify.com/c/Shopify-APIs-SDKs/We-ve-upda...

jonstaab··on A JavaScript-Free Front End
Unfortunately, I'm in the same boat, having only fiddled briefly with some of the newer web APIs, rather than architecting an app around service workers. My impression comes from folks like Joreteg who do the work, and from the increasing frequency with which new native-like APIs are released into browsers (though almost invariably implemented badly).

That said, even though the way service workers are registered is sort of odd, they're pretty trivial to work with once you're there. As far as resources go, MDN is always pretty solid, and this post (https://developers.google.com/web/fundamentals/primers/servi...) on Google's web dev guides is what I used to familiarize myself with them.

jonstaab··on A JavaScript-Free Front End
Henrik Joreteg (https://twitter.com/HenrikJoreteg) makes some pretty good arguments for PWAs. I've not had the chance to work on one, but when you start looking at mobile devices in particular, they do seem to be a good middle ground between the slimness of a document (web page) and the capability of a native mobile app. They're also not mutually exclusive with "no javascript" (if you do it right, which is a consideration). And they have the potential to save developers work, since you can get away with a PWA instead of native apps on 2+ platforms.
jonstaab··on A JavaScript-Free Front End
Agree that an offline-first PWA is the way to go. Not _no_ javascript, just _as little as possible_. However, I've also not seen such a good example before of how doable this is, so thanks to the author for the show-and-tell. The label/checkbox example is a new one on me, and covers pretty near 80% of my use of javascript. It's interesting how when you strip html of all the DOM api nonsense it starts to look like an exciting new framework. Forms are such a nice, declarative way to get user input.
jonstaab··on Kakoune – A Modal Text Editor
I've been using Kakoune for about a year, after a year of vim, after several years of Sublime. It has its warts, but it's way above and beyond anything I've used before. Whenever I use another editor I feel freakishly slow now. The big non-editing related thing it did for me was to make me appreciate the unix way — it really does one thing really well, leaving window management to tmux, and plugins to shell scripting, while maintaining its own client-server architecture to decouple various components. I'm not a huge fan of tmux or bash for scripting, but the open-endedness of kakoune's architecture on top of the great editing model really makes it a safe choice to invest in.
jonstaab··on Show HN: Bedug, a programming game for 3 year olds
Hey there, I'm the guy that wrote this — I just wanted to point out that the really neat thing about this (in my opinion) is that you can gather around a single screen (located at "/canvas"), and control the bugs from phones/tablets (using "/control"). This is a much easier interface for three-year-olds to use than a mouse, and adds some interactivity that kids will hopefully enjoy.

I made this for my own three year old, and so far he seems fairly underwhelmed, but we'll see where it goes.

jonstaab··on The Itsy-Bitsy, Teenie-Weenie, Very Litigious Bikini
Empire is an amazing game! I grew up playing it with my dad. So many good memories, and I think it stands the test of time; I still play sometimes. Never thought I'd run into its author on HN!
jonstaab··on NULL: The worst mistake of computer science? (2015)
Thanks for the article! I've often heard that null is bad, but haven't ever seen such a thorough, readable explanation.

Just so I can think it fully through for myself, it seems that the problems with null are:

1. Its semantics are different from whatever type it is substituted for, so can't be used as a value

2. Superficially, it looks identical to a missing record value. This difference might be something you want to ignore (isNullOrEmpty), or something you care about (cache miss or hit with null)

3. It is used both for missing data, and missing functionality, which confuses two separate systems.

I agree that null as a type generally works better than null as a value, but I don't know if you can always articulate it as a type, especially in dynamic languages. A pragmatic solution seems to be a combination of:

- A Maybe type or monad. This forces you to unpack the nullable semantics of the thing, either in the type system or by unwrapping the value. A Maybe monad is a well designed interface for dealing with the edge cases, but it doesn't make the edge cases go away. This eliminates problem #1, and manages problem #2.

- Nil punning. (concat nil nil) yields an empty list in clojure. Same for +, string/join, etc. This is really similar to Monads/Types, but switches the responsibility for handling null intelligently from the data structure to the standard library. Putting null in the type forces you to opt in to null; nil punning forces you to opt out. This makes for more terse code, which is nice, but probably has a slightly narrower scope of application than monads, since it tackles problem #1 by making it make sense in most cases rather than eliminating it entirely, and nil punning doesn't always make sense. Incidentally, this seems closest to PHP's and javascript's strategy; their real problem is that they extend nil punning to cases where nil isn't involved (1 + '1' anyone?).

- Key or attribute errors. This is sort of a fallback to compensate for failing to handle the null case, but often works well when something just "shouldn't be null". This is probably just a substitute for a lack of compiler checks, but works well enough in the python world; sometimes failing hard is the right thing.

- Distinction between code and data. I like higher-order functions, so I'll just say that "sometimes data includes functions". But in most cases, the function you're calling should be resolved at compile time. Interfaces should be fully implemented, and (as in python), there should be a distinction between missing functionality (AttributeError) and missing data (KeyError).

Ultimately, it seems to be a question of language/api/user interface design: there is a difference between present, present and empty, and absent. Regardless of what strategy you use to manage the difference, there has to be one.

← PreviousPage 6 of 8Next →