Hacker Newsnew | past | comments | ask | show | jobs | submit | grncdr's commentslogin

I was investigating that for entirely unrelated reasons just yesterday and the answer so far seems to be "none". You can patch the server to serve the locally built frontend and it all works just fine.


> rails 1 codebase to rails 8

A bit off topic, but Rails *1* ? I hope this was an internal app and not on the public internet somewhere …


haha no it's an old (15years old) abandoned enterprise app running on-prem that hasn't seen updates in more than a decade.


Wow Rails 3 came out 15 years ago, so that thing started life out of date.


> enterprise app

> started life out of date

That tracks my experiences.


I believe it’s slightly different in that I can declare a value (or parameter) of type T and know that it can’t be null/invalid.

Consider this Java method:

    void frobnicate(bar Bar)
    {
        // is bar null? Who knows?
    }

To get the same behavior in Helix, one would have to declare the parameter type as “Bar?”. If the parameter type is plain “Bar”, callers can still pass you a “Bar?”, but presumably you’d get an NPE at the call site and not somewhere further down the stack.

I’ve never heard of this language before today and don’t have an opinion on it, but I do find the Questionable Types interesting: sort of collapsing Option and Result into one very concise notation.


Ah, I guess that's a good point.

You get safety for the non-questionable types. But it seems like if you're going to have questionable types, you're better off not letting users silently treat them as if they aren't questionable and then risk crashing at runtime.


This is a let-down, the user expectation here is compile-time checking (not runtime NPEs)


One simple idea* would be an option to exclude certain React elements from auto translation. That would allow users to handle these specific cases “manually” while still reaping the benefits of the automated system the other 99% of the time.

* worth exactly what you paid for it ;)


...or having an "override" file that allows manual specification regardless about what the LLM spits out.


we've added support for both these cases actually! :)

1. `data-lingo-skip` - excludes a jsx node from i18n 2. `data-lingo-override-<locale code>` - overrides version in <locale code> language with a custom value 3. also `data-lingo-context`

(docs, perhaps, aren't yet the best, but here they are: https://lingo.dev/compiler/configuration/advanced)


Ah that’s great. I simply hadn’t read the docs that far


It’s an interesting idea, but how would such a system handle queries that should cross tenant boundaries? (E.g. system-level reporting)


1. Go around pgcat/pgdog?

2. I have had good luck using pragma comments for that kind of thing: a way to communicate to the infrastructure without the target system seeing it

3. From the "malicious compliance department," I would also accept "include it but in a tautological way" (tenant_id = :ten_id or tenant_id <> :ten_id)


Echoing the comment below (above), since we can fingerprint queries using the Postgres parser, we can create an allow list and a more fine-grained ruleset.


> Since XHP executes on a server that emits HTML, the most that you can do relatively seamlessly is to replace parts of an existing markup with the newly generated HTML markup from the server by updating innerHTML of some DOM node.

It’s a very long post so maybe I missed it, but does Dan ever address morphdom and its descendants? I feel like that’s a very relevant point in the design space explored in the article.


I’m curious, are you running GoodJob in the same database as the application? For smaller scale stuff this is super convenient, but I wonder if it will become a problem at higher loads.


> If you have a single page front end setup, and a "RESTful" backend

Rails really doesn't encourage this architecture, quite the opposite in fact.

> designers and users of the applications I have been building for years never want just one model on the screen.

... and this is where Rails excels. When you need to pull in some more data for a screen you just do it. Need to show the most recent reviews of a product in your e-commerce backend? It's probably as simple as:

    <%= render @product.reviews.order(created_at: :desc).limit(5) %>
Of course this can have the opposite problem of bloated views taking forever to load, but Rails has lots of caching goodies to mitigate that.

---

Going back to the GP post

> Rails feels like it _prefers_ you build "1 model = 1 concept = 1 REST entity"

That's definitely the simple path, but there are very few constraints on what you can do.


To add to what others mentioned, there’s also https://github.com/livebook-dev/pythonx which embeds a Python interpreter into your elixir program.


> People get distracted by the idea of pure capability systems. See the thread above. Pure caps don't work, …

I’m one of those “distracted” people who has never gone far enough with a capabilities-based language to figure out why they don’t work.

I read a lot about E and tinkered with Pony, and it seems that the biggest barrier is bootstrapping/network effects (e.g. lack of available libraries & expertise) rather than something intrinsic to a capabilities oriented security model.

In contrast, I only just learned about Javas SecurityManager from an earlier comment on this post. Reading the documentation at https://docs.oracle.com/javase/8/docs/api/java/lang/Security... leaves me with an impression of more complexity for integrators (as you noted) and a need for vigilance at system boundaries by runtime implementors. Building on reference capabilities seems much much simpler, but maybe that’s just my lack of experience ?

> There are some conceptual and social difficulties with this kind of security, at some point I should write about them.

I guess my comment is a long way of saying: please do!


The SecurityManager actually was a capability system! It just wasn't a pure capability system. Instead, capabilities enabled finer grained permissioning and optimization, which is IMO usually the right way to use them.

The problem with a pure caps system is that basically all software expects to have some ambient permissions. Changing that assumption not only breaks every API of every library, but reduces the usability by a lot too. For instance, it's commonplace for libraries to support tweaks to their behavior via environment variables or (in Java) system properties, but, those could also contain secrets, so that has to be a permission. In a pure capability design there's no way to grant a library the permissions it needs statically, instead a higher privileged component has to either do the read itself and pass the answer to the lower privileged part, or wrap its power into a capability object that exposes only what's needed. But then who writes that object? It's boilerplate so it'd make sense for it to come from the library itself, but, oh, that doesn't work because it's that code that's enforcing the security boundary. The user of the library has to write the code (or copy/paste and review it).

The SecurityManager design had some flaws but was basically a correct design for sandboxing most libraries (those that can't exfiltrate data obtained via side channel attacks):

1. You could assign libraries static sets of permissions, or not.

2. You could build strong capabilities using a mix of taking away a libraries reflection permissions, and AccessController.doPrivileged which terminated the intersection stack walk.

For instance, imagine a library that reads a config file (e.g. for logging configuration). There are two ways to handle this. You could change the library API so it requires a file capability. Java lets you do that - File[Channel] are capability objects. But, this is tedious for the developer. Now to use the library they have to write boilerplate to open the config file themselves so they can pass the opened capability in, which in turn means that basics like the location of the file can't be encapsulated in the library itself.

Alternatively you can just ship the library with a permissions file written in a simple DSL, that has a line like

    grant my-lib open ~/.config/my-lib/logging.json
Now the library API doesn't have to change, the developer doesn't have to open the file for the library, and the permissions can evolve alongside the evolution of the logging feature itself. The library user only has to review the permissions file when it changes, if they care about sandboxing, or ignore it if they don't.

This is much more usable! Capabilities in this model are still useful, but are the preserve of some special cases. For instance, complex permission checks can be done once and then encapsulated into a capability object (this is how file capabilities work, all the authorization logic is only on the open path and calling read or write is a much cheaper check). And of course APIs can be extended smoothly to support this, any time you have an API like:

    void setConfigFilePath(String path);
you add another method

    void setConfigFile(File file);
and make the first version delegate to the second. Now the library can have its permissions removed and be given a file capability instead, if that makes more sense.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: