今日已更新 351 条资讯 | 累计 27526 条内容
关于我们

标签:#os

找到 630 篇相关文章

AI 资讯

How to add license keys to a SwiftUI macOS app (in under an hour)

You built a Mac app, you want to sell it outside the App Store, and now you need licensing: a key the customer enters, an activation that sticks, and feature gates that hold up offline. Here's how to do it in an afternoon without standing up a backend. Note: this is cross-posted from the Keylight blog . I build Keylight, so this uses it as the worked example — the shape of the solution applies whatever SDK you choose. The three things licensing actually has to do Strip away the marketing and every licensing system does exactly three jobs: Activate — turn a key the user pastes in into proof-of-purchase bound to this device. Verify — on every launch, confirm that proof is still valid, including offline . Gate — unlock features based on the tier/entitlements the license carries. If you build this by hand you're writing a server, a crypto layer, and a state machine. The point of an SDK is to skip all three. 1. Add the SDK Add the Swift package in Xcode (File ▸ Add Package Dependencies) pointing at the Keylight Swift SDK, then configure it once with your tenant key at app launch: import Keylight let keylight = Keylight ( tenant : "your_tenant_key" ) 2. Activate a key Give the user a text field and call activate . This is the one online step — it exchanges the key for a signed, device-bound lease that's stored locally: do { try await keylight . activate ( key : enteredKey ) // lease stored — the app is now licensed on this device } catch { // show the user why: invalid key, device limit reached, etc. } 3. Verify on launch (offline-safe) On every subsequent launch you don't hit the network. The SDK verifies the stored lease's Ed25519 signature locally and hands you a state: switch keylight . checkOnLaunch () { case . licensed ( let lease ): unlockApp ( entitlements : lease . entitlements ) case . trial ( let daysLeft ): runTrial ( daysLeft : daysLeft ) case . expired , . invalid : showActivationScreen () } No server call, so the app opens instantly and works on a plane. Th

2026-06-27 原文 →
AI 资讯

I compared the licensing tools for my indie Mac app — the honest breakdown

I needed to license a macOS app I sell outside the App Store. I went down the rabbit hole so you don't have to. Here's the honest breakdown — what each tool is genuinely good at, and where it stops. No tool is "best"; they're good at different things. The two questions that decide everything Before the tools, answer these: Do you need real offline verification? (Desktop apps usually do — see firewalls, planes, air-gapped machines.) This eliminates the "license key is just a string you check over HTTP" options for serious use. Do you want payments handled too, or do you already have Stripe? Some of these are licensing-only; some are merchant-of-record that also do keys. The licensing-first tools Keygen — the one most people name first. Language-agnostic API, deep policy engine, open-source, self-hostable. Genuinely powerful. The cost is that it's primitives : you bring your own payments, wire the webhooks, and write the client code. Pick it when you want maximum control and don't mind assembling the flow. Cryptolens — classic license-key system with offline verification via signed responses. Strong .NET heritage. Solid if you're on Windows/.NET and want the traditional key + activation-count model. LicenseSpring — enterprise-leaning. Floating licenses, air-gapped activation, node-locking. Overkill for a solo indie app, right at home if you're selling into companies with offline/dark-site requirements. The payments-first tools (keys as a feature) Lemon Squeezy / Polar — merchant of record, so they handle sales tax for you, with a license-key API bolted on (activate / validate / deactivate). Great for getting paid fast across borders. The licensing side is basic — keys are essentially strings with an activation limit; offline verification isn't really their thing. Gumroad — the simplest possible "sell a thing, get a license key, verify over one endpoint." Fine for a cheap utility where piracy isn't worth fighting. Not infrastructure. StoreKit — only relevant if you shi

2026-06-27 原文 →
AI 资讯

How offline license activation actually works

If you ship a desktop app outside an app store, you eventually hit the same wall: how do you check a license when the user is on a plane, behind a corporate firewall, or just offline? Calling your server on every launch isn't an option. Here's how offline activation actually works, without the hand-waving. The naive version, and why it breaks The first thing everyone reaches for is "call home on launch, get back yes/no." It works in the demo and fails in the wild: No network = no app. Fail-closed locks out paying customers. Fail-open means anyone who blocks your domain runs free. Both are bad. A boolean is forgeable. If your app trusts a {"valid": true} response, a proxy or a patched DNS entry returns that for free. The fix isn't a better endpoint. It's moving the trust off the network and onto cryptography. The model that works: signed leases The durable pattern is a cryptographically signed lease (Keygen calls these license files, Keylight calls them leases — same idea): On first activation, the device talks to the server once . The server returns a small signed document: the license state, an expiry, the device binding, and any entitlements (which features/tiers are unlocked). The document is signed with the server's private key (Ed25519 is the modern choice — small, fast, boring in the good way). Your app ships the matching public key and verifies the signature locally on every launch. No network needed. Because the app only ever verifies with a public key, there's nothing secret in the binary to steal, and a forged lease fails the signature check. That's the whole trick: the server vouches once, math vouches forever after. first launch ──► server signs lease (Ed25519, private key) ──► stored on device every launch ──► app verifies signature (public key) ──► no network Device binding (so one key isn't infinite installs) A lease is bound to a device so a single license can't be pasted onto a thousand machines. The lease embeds a device fingerprint, and the SDK ch

2026-06-27 原文 →
AI 资讯

Redis Isn't PostgreSQL: Building a Hybrid Change Data Capture Runtime in Ruby

I Built Commercial Redis CDC Source Drivers for Ruby — Here's What I Learned For the past couple of years I've been building a Change Data Capture (CDC) ecosystem for Ruby. Like many CDC projects, it started with PostgreSQL. PostgreSQL's Write-Ahead Log (WAL) is an excellent source of truth: durable, ordered, replayable, and well understood. It provides exactly the properties you want when you're building reliable event pipelines. But the deeper I went into distributed systems, the more I realized something important. Many systems don't observe change from PostgreSQL first. They observe it from Redis. Redis often sits at the front of modern architectures: Redis Streams carry application events. Pub/Sub distributes transient state changes. Keyspace notifications react to cache invalidation and key expiry. Redis Cluster routes events across multiple primaries. In many systems, Redis sees a change before PostgreSQL ever commits it. That raised an interesting question: Can Redis become a first-class Change Data Capture source? The obvious answer is "yes." The interesting answer is "yes—but not in the same way PostgreSQL does." That distinction eventually became cdc-redis-pro , a commercial Redis source driver for the Ruby CDC ecosystem. This article isn't a product announcement. It's an engineering write-up about the architectural decisions behind the project, the tradeoffs Redis forces you to make, and the execution model that ultimately emerged. Redis Doesn't Have One CDC Interface One misconception I frequently encounter is the assumption that Redis has an equivalent of PostgreSQL's WAL. It doesn't. Instead, Redis exposes several completely different mechanisms for observing change. Source Delivery Replay Streams At-least-once Yes Pub/Sub At-most-once No Sharded Pub/Sub At-most-once No Keyspace Notifications At-most-once No At first glance they all look like "events." Operationally they're completely different systems. Streams are durable. Pub/Sub isn't. Keyspace not

2026-06-27 原文 →
AI 资讯

Post-Mortem Best Practices That Actually Drive Change

The Post-Mortem Nobody Learns From I've sat through hundreds of post-mortems. Most follow the same pattern: something breaks, someone writes a Google Doc, we have a meeting, we list action items, nobody follows up, the same thing happens again in 3 months. Here's how to break the cycle. The Blameless Culture Trap "Blameless" doesn't mean "actionless." The biggest failure mode I see is teams that use blameless culture as an excuse to avoid accountability. Blameless means: we don't punish the person who pushed the bad deploy. Blameless does NOT mean: nobody is responsible for fixing the systemic issue. My Post-Mortem Template # Incident: [SERVICE] [SYMPTOM] on [DATE] ## Impact - Duration: X minutes - Users affected: N - Revenue impact: $X - SLO budget consumed: X% ## Timeline (UTC) - HH:MM - First alert fired - HH:MM - On-call acknowledged - HH:MM - Root cause identified - HH:MM - Fix deployed - HH:MM - Service recovered - HH:MM - All-clear declared ## Root Cause [2-3 sentences. Technical but readable.] ## Contributing Factors 1. [Factor that made the incident possible] 2. [Factor that made detection slow] 3. [Factor that made resolution slow] ## What Went Well - [Something that worked] - [Something that helped] ## What Went Wrong - [Process failure] - [Technical gap] ## Action Items | Action | Owner | Priority | Due Date | Status | |--------|-------|----------|----------|--------| | ... | ... | P1/P2/P3 | ... | Open | ## Lessons Learned [1-2 paragraphs of genuine insight] The Action Item Problem Action items from post-mortems have a 30% completion rate industry-wide. That's terrible. Here's why: Too many items (I've seen post-mortems with 15 action items) No clear ownership No deadline No follow-up mechanism Competing with feature work The Fix: Three Rules Rule 1: Maximum 3 action items per post-mortem. If you can't narrow it to 3, you haven't identified the real problems. Rule 2: Every action item gets a JIRA ticket linked to the next sprint. Not "someday." Not "bac

2026-06-27 原文 →
AI 资讯

How I built multi-tenant Row Level Security with Aurora PostgreSQL for a B2B SaaS — H0 Hackathon

I'll be honest: I almost did multi-tenancy the wrong way. When I started building InspectIQ "a SaaS platform for Florida home inspectors" my first instinct was to add a tenant_id column to every table and filter it in the application layer. Every query would have a WHERE tenant_id = :current_tenant clause. Simple, familiar, done. Then I thought about what happens when you forget one. One missing WHERE clause. One endpoint that skips the filter. One inspector sees another inspector's client data. In a home inspection business, that's not just a bug — it's a HIPAA-adjacent nightmare and a trust-destroying moment with your first customer. So I did it properly from day one: Row Level Security at the database layer. What is Row Level Security? RLS is a PostgreSQL feature that lets you define policies directly on tables. When a user queries a table, the policy runs automatically, before your application code even sees the results. You can't forget to apply it. You can't bypass it with a careless JOIN. It's enforced at the lowest possible layer. For a multi-tenant SaaS, this is exactly what you want. How I implemented it Every table in InspectIQ has this pattern: ALTER TABLE inspections ENABLE ROW LEVEL SECURITY ; ALTER TABLE inspections FORCE ROW LEVEL SECURITY ; CREATE POLICY tenant_isolation ON inspections USING ( tenant_id = NULLIF ( current_setting ( 'app.current_tenant_id' , true ), '' ):: uuid ); The FORCE is important — it applies the policy even to the table owner. No superuser backdoor. The tenant context comes from the JWT. When an inspector logs in, their tenant_id is embedded as a custom Cognito claim. The FastAPI middleware extracts it and sets it at the start of every request: await session . execute ( text ( f " SET LOCAL app.current_tenant_id = ' { tenant_id } '" ) ) SET LOCAL scopes the setting to the current transaction. When the transaction ends, it's gone. No leakage between requests. Aurora PostgreSQL Serverless v2 I'm running this on Aurora PostgreSQ

2026-06-26 原文 →
AI 资讯

Two Hours of Deliberation

Nine jurors. Two hours of deliberation. Twenty-six claims at the original federal complaint's peak. Three surviving claims at trial. Zero claims surviving the verdict. One hundred fifty billion dollars of maximum disgorgement exposure if the verdict had gone the other way. One hundred thirty billion dollars of OpenAI Foundation equity stake under the October 28, 2025 recapitalization. Thirty-eight million dollars of total Musk contributions per his sworn trial testimony. Forty-four million per the legal complaint. Eight years from the January 2, 2016 Sutskever-Musk "less open / Yup" email exchange to the August 2024 federal filing date. Three years of statute-of-limitations runway on the breach-of-charitable-trust claim; two years on the unjust-enrichment claim. The verdict in Musk v. Altman came in this morning at the federal courthouse on Clay Street in Oakland, before Judge Yvonne Gonzalez Rogers in the Northern District of California. The companion piece, The Calendar Technicality , makes the doctrinal argument that the procedural dismissal is the substantive determination California charitable-trust law would have produced on the merits as well. This piece takes the same conclusion through the numbers. The dollar-and-time math closed the merits door before the doctrinal door even came into view. Two hours, in context Federal-court civil-trial deliberations on complex commercial cases typically run between one and five days. The Administrative Office of the U.S. Courts' annual judicial-business reports show median civil-jury deliberation in the multi-day range for cases with three or more issues to resolve and dollar exposure above one billion. The two-hour deliberation in Musk v. Altman is roughly one to two standard deviations below the median for cases of this complexity. The brevity is not a function of jury inattention. The trial ran three weeks. Roughly four hours of testimony came from Altman alone on May 12, with cross-examination opening with Musk's lea

2026-06-26 原文 →
AI 资讯

The Illusion of Microservices: Why the Modular Monolith is Once Again the Gold Standard in Architecture

Throughout my career, transitioning between CTO roles and, more recently, focusing purely on distributed systems architecture and high-performance engineering, I've seen many architectural patterns rise and fall. But few have caused as much silent damage to company bottom lines as the premature adoption of microservices. Over the last decade, the industry bought into the idea that, in order to scale, you needed to split your system into dozens (or hundreds) of independent services. The practical result I find in most companies? The creation of the dreaded "Distributed Monolith." The Anatomy of Waste: Networks vs. Memory The hard truth we need to face with maturity is that microservices primarily solve problems of organizational scale (Conway's Law), not necessarily performance. If your engineering team isn't the size of Netflix or Uber, prematurely fragmenting your codebase is shooting yourself in the foot. Technically, what happens when we break down a monolith without the proper domain boundaries? We trade extremely fast and cheap local function calls (resolved in the processor's L1/L2 Cache) for slow and expensive network calls (TCP/IP). We start spending an absurd amount of computational time on constant JSON serialization and deserialization, and the AWS bill explodes with internal traffic costs (egress/ingress) between Availability Zones (AZs). You haven't scaled your application; you've merely added network latency and infrastructure complexity. The Return of the Modular Monolith True seniority in software engineering isn't about mastering the most complex architecture of the moment, but having the wisdom to know when not to use it. That's why the Modular Monolith has consolidated itself as the initial gold standard for new projects and restructurings. In a well-designed Modular Monolith (and languages with strong type systems and strict scope control, like Rust, shine absurdly well here), you maintain the logical separation of domains. Modules are independen

2026-06-26 原文 →
AI 资讯

Localizzare in massa la scheda App Store con ASC CLI (e perché conviene davvero)

Dai metadati in una lingua a 20 localizzazioni senza impazzire tra click e schermate: un flusso pratico per indie e piccoli team. Localizzare un’app non significa solo tradurre le stringhe dell’interfaccia. Una buona parte dell’acquisizione organica passa dai metadati su App Store Connect : titolo, sottotitolo, descrizione e keyword. Il problema è che, quando provi a farlo “a mano” dal pannello web, diventa subito un lavoro di pura resistenza: apri la scheda, cambi lingua, compili i campi, salvi, ripeti. Ora moltiplica per 10–20 lingue. Per molti indie (e in generale per chi ha poco tempo e zero voglia di click ripetitivi) il punto di svolta è usare ASC CLI per rendere questa attività automatizzabile, ripetibile e verificabile . Perché la localizzazione dei metadati è un caso d’uso perfetto per una CLI Dal punto di vista del flusso di lavoro, i metadati App Store hanno tre caratteristiche che li rendono ideali per l’automazione: Sono campi strutturati (title, subtitle, description, keywords): non stai “inventando” contenuti ogni volta, stai trasformando contenuti. Sono ripetitivi per lingua : la sequenza di operazioni è identica, cambia solo la locale. Sono tanti : più lingue aggiungi, più l’approccio manuale scala male (tempo, errori, incoerenze). Con una CLI, invece, il lavoro si sposta dal “fare cose” al definire un processo : prendi i metadati di partenza, generi le varianti linguistiche, applichi l’update in batch. Cosa conviene localizzare (e cosa no) In genere ha senso includere in un passaggio di localizzazione “massiva”: App name / title (attenzione ai limiti e ai trademark) Subtitle (spesso è la parte più ASO-oriented) Description (qui conta più la leggibilità che la traduzione letterale) Keywords (campo delicato: va adattato, non tradotto alla cieca) Al contrario, è meglio trattare con più cautela: Claim e frasi marketing molto creative : in alcune lingue risultano innaturali se tradotte letteralmente Keyword strategy : la ricerca utenti cambia per mercat

2026-06-25 原文 →
AI 资讯

Self-host n8n on a VPS with Docker

n8n is the kind of tool you start using lightly and then quietly route half your operations through. At which point "it's running on someone's cloud seat, metered per execution, with my API keys living on their servers" starts to feel less great. Self-hosting fixes all three — flat cost, no execution cap, and your keys stay on a box you own. With Docker it's a fifteen-minute job. How much server it actually needs Honest numbers first, so you don't over- or under-buy: ~2 GB RAM is the sweet spot — n8n plus its Postgres database plus normal workflows sit comfortably here. 1 GB works if your workflows are light, but you'll notice it on bigger runs. 4 GB if you do heavy parallel executions or push large payloads through. n8n isn't CPU-hungry at rest; it spikes during runs. A 2-core box is fine for most setups. (More on matching specs to workload in the sizing guide .) The Docker setup On a fresh Ubuntu/Debian box, install Docker: curl -fsSL https://get.docker.com | sudo sh Make a folder and a docker-compose.yml — n8n with a persistent volume and Postgres: services : n8n : image : docker.n8n.io/n8nio/n8n restart : always ports : - " 127.0.0.1:5678:5678" environment : - N8N_HOST=n8n.yourdomain.com - N8N_PROTOCOL=https - WEBHOOK_URL=https://n8n.yourdomain.com/ - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=db - DB_POSTGRESDB_PASSWORD=change-me volumes : - ./n8n-data:/home/node/.n8n depends_on : [ db ] db : image : postgres:16 restart : always environment : - POSTGRES_PASSWORD=change-me - POSTGRES_DB=n8n volumes : - ./db-data:/var/lib/postgresql/data sudo docker compose up -d Two things worth pointing out: the volumes ( n8n-data , db-data ) are what keep your workflows alive across restarts and upgrades — don't skip them. And n8n is bound to 127.0.0.1 , not 0.0.0.0 — it's not exposed to the internet directly. That's deliberate; the next step handles access safely. Access: HTTPS or a tunnel Public URL (needed for OAuth nodes and webhooks): point a subdomain at the server and run

2026-06-25 原文 →
AI 资讯

Your Database Will Be Breached Someday. The Question Is: Will Passwords Be Inside?

Most developers think password hashing is about authentication. It's not. Authentication is just a side effect. Password hashing exists for a much darker reason: because databases get stolen. Every year, companies invest millions in firewalls, monitoring systems, cloud security, and access controls. Yet breach after breach continues to make headlines. The uncomfortable truth is that security teams don't assume a breach will never happen. They assume it eventually will. And when that day comes, one question determines whether the incident becomes a minor security event or a full-scale disaster: Did you hash the passwords? The Difference Between an Incident and a Catastrophe Imagine an attacker gains read access to your production database. Not a far-fetched scenario. A leaked backup. A vulnerable API. A compromised employee account. A misconfigured cloud bucket. The attacker runs a simple query: SELECT email , password FROM users ; If your system stores passwords in plain text, the breach is over. The attacker already won. No advanced techniques. No brute force. No expensive infrastructure. They now possess something more valuable than your database itself: your users' digital identities. Because users rarely reuse databases. They reuse passwords. The same password protecting an account on your platform might also unlock their Gmail, GitHub, LinkedIn, banking app, or company VPN. What started as your security problem instantly becomes everyone else's. This Is Not Theoretical History has repeatedly shown what happens when passwords are handled incorrectly. The RockYou breach exposed more than 30 million passwords stored in plain text. Attackers didn't need to crack anything. They simply read the data. Years later, those leaked passwords were still appearing in credential stuffing attacks across the internet. A single backend decision survived longer than the company itself. That's the thing about password leaks. They don't expire when the incident report is published.

2026-06-25 原文 →
AI 资讯

Microsoft introduces cheaper Surface devices with half the memory

Microsoft just added a cheaper 12-inch Surface Pro and 13-inch Surface Laptop to its lineup. Both models come equipped with 8GB of RAM instead of 16GB, costing $849 for the specced-down Surface Pro and $949 for the Surface Laptop, as spotted earlier by Windows Central. When the 12-inch Surface Pro and 13-inch Surface Laptop launched […]

2026-06-25 原文 →
AI 资讯

I Built a Messenger That Works Without the Internet — And It Changed How I Think About Privacy

A quiet experiment in Bluetooth, offline communication, and why we gave up too much when we handed our conversations to the cloud. The last time I was truly unreachable, I was in a place with no cell signal and no Wi-Fi. And I realized something strange: I had no way to send a message to the person sitting three feet away from me — because every app on my phone needed the internet to do it. That felt wrong. We've built the most sophisticated communication technology in human history, and somehow it all routes through a handful of servers in Northern Virginia before reaching someone in the same room. So I built Bluetoosh. The Premise: What If the Network Was Just… You and Me? Bluetoosh is a peer-to-peer messenger that runs entirely over Bluetooth. No internet. No servers. No accounts. No cloud storage. Just two devices, talking to each other the way devices were always capable of doing — directly. You open the app. You see who's nearby. You start a conversation. That's it. No phone number required. No email verification. No terms of service asking you to agree that your metadata might be used for advertising. The only network involved is the six feet of air between you and the other person. Why Bluetooth? Bluetooth is one of the most underrated communication protocols we carry around every day. Your phone already has it. Your laptop has it. Most people use it for headphones and nothing else. But Bluetooth is capable of much more. It can discover nearby devices, establish encrypted connections, and transfer data — all without touching the internet. The range is roughly 10–30 meters in open space. That covers a room, a floor, a campsite. Bluetoosh uses both BLE (Bluetooth Low Energy) and Classic Bluetooth, plus Google Nearby Connections for mesh-style discovery. In practice, this means you can find people around you, chat, share files, and even make voice calls — all completely offline. What It Actually Does Here's what surprised me most while building this: offline co

2026-06-25 原文 →