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

标签:#os

找到 889 篇相关文章

AI 资讯

iOS Safari can't decode your .mov, and the reason is 2 bytes deep in the container

Our tool transcribes audio in the browser — Whisper running locally via transformers.js , no upload. It worked fine, until analytics showed something too clean to be a coincidence: .mov uploads on mobile failed 100% of the time. Not 90%. Every single one. Desktop had never reported a single .mov failure. This is what I found, and how it got fixed without pulling in ffmpeg.wasm or WebCodecs. The 30-second reproduction I took one AAC audio track and put it in two containers — same encoder, same bytes for the audio itself, only the wrapper differs: const buf = await file . arrayBuffer (); await new AudioContext (). decodeAudioData ( buf ); On an iPhone 17 Pro simulator (iOS 18.7 / Safari 26.5): File iOS Safari Chromium sample.mov (ftyp qt ) EncodingError: Decoding failed OK sample.mp4 (ftyp isom ) OK OK So it isn't the codec. It's the container. The obvious fix that doesn't work First instinct: it's the brand in the ftyp box. Patch qt → isom , four bytes, done. It still fails. I'm writing this down so nobody else burns an afternoon on it. The ftyp brand is not what Safari looks at. The difference lives inside moov . The actual root cause Dig down to moov → trak → mdia → minf → stbl → stsd — the sample description that tells the decoder how the audio is encoded. Both files carry an mp4a entry. They are not the same mp4a entry: QuickTime writes: MP4 expects: version = 1 <— version = 0 compressionID = -2 (fffe) <— compressionID = 0 + 16 bytes of v1 extension <— (absent) esds wrapped in a 'wave' box <— esds is a direct child extra 'chan' channel layout (absent) iOS Safari's decodeAudioData only accepts a version 0 audio sample entry. Chromium accepts both — which is exactly why desktop never saw this and mobile never survived it. That version field is a uint16 . Two bytes decide whether the file plays. The fix: rebuild the container, don't touch the codec Since the audio bitstream is already valid AAC, nothing needs to be re-encoded. The job is pure byte plumbing: extract

2026-08-31 原文 →
AI 资讯

We put an MCP endpoint in 49 business apps. Here is what a read-only key can and cannot do to an invoice register.

We build small self-hosted business tools, and since our 3.0 release every one of them except our AI client answers the Model Context Protocol at POST /mcp . Forty-nine of them. That was a large enough change, applied uniformly enough, that the interesting engineering question stopped being "how do we add MCP" and became "what should a language model be allowed to do to a live invoice register." This post is about the second question, because it is the one that actually matters and the one most MCP integrations answer by accident. The boring part first: the handshake There is nothing vendor-specific in it. Three facts: The address. https://your-install/mcp - your server, your domain. The key. An Authorization: Bearer apk_... header. The transport. MCP over streamable HTTP, stateless. One request in, one response out. That is the whole contract. In Claude it is one CLI line: claude mcp add --transport http invora https://your-install/mcp \ --header "Authorization: Bearer apk_xxxx" In the OpenAI Responses API it is one entry in the tools array: { "type" : "mcp" , "server_label" : "invora" , "server_url" : "https://your-install/mcp" , "authorization" : "apk_xxxx" , "require_approval" : "never" } Clients that keep servers in a config file take the same three fields under a different set of key names. n8n's MCP Client node takes the URL and the same Authorization header. And if you would rather not use a client at all, it is plain JSON-RPC 2.0 over one POST: curl -X POST https://your-install/mcp \ -H "Authorization: Bearer apk_xxxx" -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' We implemented the protocol rather than an integration with a particular vendor, which means clients that do not exist yet will work too. That is the main argument for MCP over building N bespoke connectors, and it is a good one, but it is not what this post is about. The part that took the actual thinking Once your invoice register speaks a protocol tha

2026-08-31 原文 →
AI 资讯

Hybrid encryption: why combine classical and post-quantum cryptography

When a new cryptographic algorithm appears, a tension shows up: classical algorithms such as X25519 or Ed25519 have resisted attacks for years, but are vulnerable to a future quantum computer; post-quantum ones such as ML-KEM or ML-DSA resist quantum attacks, but are newer and less tested. Hybrid encryption resolves the tension: use both at once . The idea in one sentence Combine a classical and a post-quantum algorithm so that the system only breaks if both fail simultaneously . A classical attacker would have to break the post-quantum algorithm; a quantum attacker would have to break the classical one and the post-quantum one. You gain security against the future without betting everything on a young algorithm. Two places to apply it Key exchange (encrypting for a recipient). You combine: X25519 — classical key exchange, fast and heavily tested. ML-KEM-1024 — NIST's post-quantum key encapsulation mechanism, at its highest level. The two resulting keys are mixed with a context-bound derivation function (HKDF), so that neither one alone is enough. Digital signatures (authenticity). You combine: Ed25519 — classical signature. ML-DSA-87 — NIST post-quantum signature. The message is accepted only if both signatures verify — an AND combiner. One principle that never breaks There is a golden rule in cryptography, Kerckhoffs's principle : a system must be secure even if the attacker knows its entire design; security lives in the key , not in hiding the format. A good hybrid system uses public, audited primitives — XChaCha20-Poly1305 to encrypt, Argon2id to derive keys from passwords, HKDF to separate domains — and never invents its own cryptography . How Quipu applies it Quipu is a free library implementing exactly this approach for data at rest : hybrid X25519 + ML-KEM-1024 encryption, hybrid Ed25519 + ML-DSA-87 signatures, and only verified primitives underneath. It targets NIST security level 5 (CNSA 2.0) and is open source, so anyone can review how it works. An honest

2026-08-31 原文 →
AI 资讯

Hacking My Own Mac App: Penetration Testing macOS Defense Boundaries in a VM

A Japanese version of this is on Zenn . I build and sell a macOS network-security menu bar app called RoamSwitch . In a previous post , I wrote about attacking my own Mac from an Arch Linux box on the same LAN to see how it handled basic reconnaissance and rogue device probes. Since then, as I kept adding features and refactoring, a nagging question kept resurfacing: Are we introducing regressions? Is our privileged helper still watertight? Did a recent update accidentally punch a hole in our packet filter rules? Manually poking at firewalls on every release is tedious and risky—messing with Packet Filter ( pf ) and root LaunchDaemons on your primary dev machine is a great way to accidentally drop your own network connection. So, to be absolutely thorough, I set up a repeatable, automated pentest suite inside a disposable macOS virtual machine on a Mac (using Tart ) to rigorously probe all 5 defense boundaries from the outside. Here is how the test harness works and what the logs showed when I attacked it. Test Architecture: Host Mac ⇄ Target Guest VM Running destructive firewall tests or killing root helpers on your daily driver is stressful. Instead, I used Tart , a lightweight macOS virtualization tool, to spin up a clean macOS Sonoma guest VM as the Target , with the Host machine acting as the Attacker . +------------------------------------+ +-----------------------------------------+ | Host Mac (Attacker) | | macOS VM (Target Guest) | | - Inbound Port Probing (nc/nmap) | -----> | - RoamSwitch 1.4.8 (Defense Engine) | | - Unauthorized HTTP Probing (curl)| Virtual | - Root Privileged Helper | | - Rogue ARP Spoofing (scapy) | Bridge | - Packet Filter (pf) Ruleset Anchor | +------------------------------------+ +-----------------------------------------+ The 5 Defense Boundaries Tested graph TD A[Automated Defense Suite] --> B[1. XPC Authorization Boundary (§3)] A --> C[2. pf Ruleset & Air-Gap Precedence (§4, §5)] A --> D[3. Port Anomaly & Global Exposure (§6)] A

2026-08-30 原文 →
AI 资讯

The Hidden Security Blind Spots in Local AI Workflows

A Japanese version of this is on Note . An increasing number of engineers and creators are running local LLMs (via Ollama, LM Studio, vLLM) and generating images with Gradio / Stable Diffusion directly on their Macs. With modern Apple Silicon unified memory, 7B and 14B parameter models run blazingly fast on-device. Many choose local AI specifically for privacy, thinking "My data never leaves my machine, so it must be secure." However, the moment developers want to test inference from their phone or a secondary laptop, they follow common online guides and set OLLAMA_HOST=0.0.0.0 or pass --host 0.0.0.0 . And right there, a critical blind spot opens up: "Wait... binding to 0.0.0.0 doesn't just expose this to my phone—it allows literally anyone on the same network to query my Mac without any authentication." As local AI tooling rapidly expands, network exposure, clipboard secrets, and model file formats remain dangerously overlooked. Here is what is actually exposed, and how we can secure our machines. 1. The 0.0.0.0 Trap: Local AI Inference Servers Are Unauthenticated by Default Whether it's Ollama ( 11434 ), LM Studio ( 1234 ), Gradio / Stable Diffusion WebUI ( 7860 ), or vLLM ( 8000 ), developers often configure OLLAMA_HOST=0.0.0.0 or pass --host 0.0.0.0 so they can test inference from a phone or a secondary laptop. The fundamental issue: almost all of these tools run without authentication by default. (Ollama has no built-in API auth at all and requires an external reverse proxy, while vLLM or Gradio require explicit --api-key or auth= configuration that is rarely set up in casual local dev environments). [Rogue Device on Shared Wi-Fi] ──── Unauthenticated HTTP Request ────> [Your Mac] Ollama (11434) - Free GPU compute hijacking - Unauthorized model downloads - Model deletion via DELETE API - Private prompt snooping If you start an inference server on 0.0.0.0 while connected to office Wi-Fi, a shared workspace, or even a home network with compromised IoT devices, an

2026-08-30 原文 →
AI 资讯

The most common reasons Apple rejects your app

Getting a rejection email from App Review feels personal. It usually isn't. Apple runs the same review process against every submission, and most rejections trace back to a small number of guidelines that come up again and again. Knowing which ones, and what they actually mean, turns a vague rejection into a fixable checklist. How often this actually happens Apple's own 2024 App Store Transparency Report puts real numbers on this. Out of 7.77 million app submissions reviewed that year, 1.93 million were rejected, roughly 25%. Of those, 295,109 were fixed and approved on resubmission. Separately, 82,509 already-live apps were removed after the fact, most commonly for guideline or design violations (42,252), followed by fraud (38,315). Apple hasn't published a breakdown of rejections by specific guideline number, so treat any listicle claiming "62% of rejections are X" as unsourced. What Apple has said, in its own commentary alongside the report, is that the most common drivers, in order, are performance and bugs, legal issues, design problems, business-model (payment) violations, and safety risks. That ordering lines up with the specific guidelines below. The guidelines that actually catch people These are pulled directly from Apple's current App Store Review Guidelines, not paraphrased from a third party. Guideline 2.1, App Completeness. Covers crashes, obvious bugs, placeholder content, broken demo accounts, and non-functional in-app purchases. If a reviewer can't get past your login screen or your app crashes on launch, this is the line it gets cited under. It's the single most avoidable category, because it's the one you can actually test yourself before submitting. Guideline 4.2, Minimum Functionality. Your app has to be more than "a repackaged website." Apple wants "lasting entertainment value or adequate utility." A thin wrapper around a web view, with no native functionality added, gets flagged here. A sub-clause, 4.2.6, specifically targets apps built from c

2026-08-30 原文 →
AI 资讯

Quipu: post-quantum encryption in pure Rust, with a Python wheel

Protecting data that must stay secret ten years from now is a problem for today : an adversary can capture your encrypted traffic now and decrypt it once quantum capability exists ( harvest now, decrypt later ). Quipu is a free hybrid post-quantum encryption library for data at rest: it combines proven classical cryptography with the new kind, so that it only breaks if both fall at once. Pure Rust, and why Quipu started out aiming at several languages: a Rust core with a C ABI on top and bindings for Python, Node and Go. It worked, but the lesson was clear: maintaining a stable C interface plus four bindings, each with its own packaging and interoperability tests, was complexity that did not pay for itself against the real goal — protecting data at rest — and it widened the attack surface with unsafe we did not want. Today Quipu is pure Rust : memory safe, no garbage collector, no first-party unsafe . And for people who do not write Rust, it ships as a native Python wheel via PyO3 — the surface that non-Rust users actually need. One codebase, one thing to audit. It is the same philosophy that guides the rest: where good cryptography exists, reuse it; simplicity is a security decision, not a convenience. Installation cargo add quipu # Rust pip install quipu-crypto # Python (native wheel, PyO3) Encrypt and decrypt in Python import quipu # Symmetric, with a passphrase blob = quipu . encrypt_stream ( b " sensitive data " , " my-passphrase " ) assert quipu . decrypt_stream ( blob , " my-passphrase " ) == b " sensitive data " # Post-quantum, for a recipient pub , sec = quipu . generate_keypair () # X25519 + ML-KEM-1024 c = quipu . encode_to_recipient ( b " secret " , pub ) assert quipu . decode_as_recipient ( c , sec ) == b " secret " What is underneath Encryption: XChaCha20-Poly1305 (authenticated AEAD). Key derivation: Argon2id (brute-force resistant) + HKDF. Post-quantum: X25519 + ML-KEM-1024 for keys; Ed25519 + ML-DSA-87 for signatures. Security level: NIST category 5

2026-08-30 原文 →
AI 资讯

Python PostgreSQL with asyncpg: Async Database Operations

Python PostgreSQL with asyncpg: Async Database Operations asyncpg is the fastest PostgreSQL driver for Python — pure asyncio, no thread overhead, and up to 3× faster than psycopg2 on typical workloads. It is the go-to choice for any async Python backend. Installation pip install asyncpg # PostgreSQL server must already be running Connect and Create a Pool import asyncio import asyncpg from datetime import datetime DATABASE_URL = " postgresql://user:password@localhost:5432/mydb " async def create_pool () -> asyncpg . Pool : pool = await asyncpg . create_pool ( DATABASE_URL , min_size = 2 , max_size = 10 , command_timeout = 30 , server_settings = { " application_name " : " myapp " }, ) print ( " Pool created. " ) return pool Schema Setup CREATE_TABLES = """ CREATE TABLE IF NOT EXISTS users ( id BIGSERIAL PRIMARY KEY, username TEXT NOT NULL UNIQUE, email TEXT NOT NULL UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS posts ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, title TEXT NOT NULL, body TEXT NOT NULL DEFAULT '' , published BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_posts_user ON posts(user_id); CREATE INDEX IF NOT EXISTS idx_posts_created ON posts(created_at DESC); """ async def setup_schema ( pool : asyncpg . Pool ) -> None : async with pool . acquire () as conn : await conn . execute ( CREATE_TABLES ) print ( " Schema ready. " ) INSERT — Adding Records async def create_user ( pool : asyncpg . Pool , username : str , email : str ) -> int : async with pool . acquire () as conn : row = await conn . fetchrow ( """ INSERT INTO users (username, email) VALUES ($1, $2) ON CONFLICT (username) DO UPDATE SET email = EXCLUDED.email RETURNING id, created_at """ , username , email , ) return row [ " id " ] async def create_post ( pool : asyncpg . Pool , user_id : int , title : str , body : str , published : bool = False , ) ->

2026-08-29 原文 →
AI 资讯

Presentation: Architecting the Data Layer for AI Agents: From Transactional Systems to MCP and Semantic Models

Fabiane Nardon shares how TOTVS prepares enterprise data for token-hungry AI agents. She discusses balancing deterministic logic and non-deterministic LLMs across precision, security, and cost. Nardon details using data mesh, low-latency database architectures, semantic ontologies, and dynamic MCP tool selection to optimize context windows and reduce token overhead in transactional systems. By Fabiane Nardon

2026-08-29 原文 →
AI 资讯

How to run internal phishing simulations for your organization (free & self-hosted)

How to run internal phishing simulations for your organization (free & self-hosted) Phishing is still how most breaches start. The single most effective defence isn't another mail filter — it's people who can spot a lure and report it. The way you build that instinct is internal phishing simulations : controlled, authorized fake-phishing tests of your own employees, paired with training the moment someone slips. This is a practical guide to doing that well — and doing it for free, on your own infrastructure, with an open-source tool. First rule: authorization, always Internal phishing simulation means testing people who have agreed to be tested — your own organization, or a client with a signed engagement scope. Point a phishing tool at anyone outside that and you're very likely breaking the law. Keep a record of your authorization, tell leadership and (per your policy/works-council rules) employees that a program exists, and never use captured data for anything but the training exercise. Good tools are built as trainers , not credential-harvesters — for example, they don't store the passwords people type into a fake login page by default. With that ground rule set, here's what a real program looks like. A good program is a loop, not a single test "Who clicked?" is where most free tools stop. A program that actually reduces risk runs four stages: Attack — send a believable lure and track engagement per person. Report — make it one click for employees to report suspicious mail, and give them credit when they do. Train — the moment someone clicks or submits, teach them what they missed. Measure — roll it all up into a human-risk score you can trend over time. You can assemble this from separate tools, or use one platform. Below I'll use VoltPhish , an open-source, self-hosted platform that does the whole loop from one Docker container. (If you only need email click-tracking, GoPhish is the classic minimal option; commercial suites like KnowBe4 or Proofpoint do all of

2026-08-29 原文 →
开源项目

Uber Builds GitFarm to Run Git Operations as a Service for Large-Scale Monorepos

Uber’s GitFarm provides Git operations as a centralized service, eliminating local repository clones across large scale monorepo workloads. The platform uses prewarmed checkouts, ephemeral sandboxes, repository synchronization, and gRPC streaming to reduce resource consumption and startup latency for automation services operating across thousands of repositories. By Leela Kumili

2026-08-28 原文 →
开发者

I Built a Small API Gateway With Real Production Problems — On Purpose

Most gateway tutorials stop at "here's how you route a request." That's the easy 20%. The hard part is what happens when a client hammers you with requests, a downstream service falls over mid-traffic, or you're staring at a 500 trying to figure out which of your four services actually caused it. I wanted to build something that hits those problems on purpose, so I put together spring-gateway-sample : a public gateway , an api-server that fans out to two downstream services, and a full observability stack sitting behind all of it. It's not a real product and never will be. But I tried to make it behave like one — including the annoying bits, like config tradeoffs and races that most demos just quietly ignore. Stack, for context: Spring Boot 4.1, Spring Cloud Gateway on WebFlux, Resilience4j, Redis, Postgres, Keycloak, Prometheus/Grafana/Tempo/Loki, and a small Vue 3 app for throwing traffic at it from a browser. The system, in one request Browser (Vue traffic simulator) │ Keycloak PKCE login + API key ▼ Gateway ── JWT + API-key auth, Redis rate limiting ──▶ routes to │ ▼ api-server ── WebClient delegation, circuit breakers, Caffeine cache ──▶ │ │ ▼ ▼ product-service pricing-service (JPA / Postgres) (JPA / Postgres) Every hop re-validates the JWT on its own — defense in depth, so the gateway isn't the single thing standing between the internet and the data. The gateway also checks an API key on top, because a JWT tells you who the user is, not which client application is calling on their behalf. You need that second identity if you want per-client rate limits or the ability to revoke one app's access without touching anyone else's. Two checks, one specific order Every request needs a Keycloak JWT and an API key, and the order they're checked in isn't an accident: Missing or expired JWT → 401 , before the API key is even looked at. Valid JWT, bad API key → 401 , but a different error code. Both valid, wrong role → 403 . Why bother with the ordering? Because "you're no

2026-08-28 原文 →
AI 资讯

What is an AI Agent Phone?

An AI agent phone is a real, or cloud-hosted, smartphone that an LLM-powered agent can operate on its own. It sees the screen, taps, swipes, types, opens apps, and completes multi-step tasks the same way a person would. Instead of calling an API, the agent uses the phone directly, the same Instagram, banking, or delivery app you'd use, driven by a model instead of a thumb. The phrase gets used two ways in 2026. Some products sell phone numbers for AI agents, voice and SMS. That's not this. Here, an AI agent phone means the device itself as something an agent controls, a full Android or iOS handset that becomes an autonomous actor. If you've heard the pitch give your AI agent a phone, this is it. Why a phone, not a browser? Most agent tooling lives in the browser, or in desktop computer use. That misses where people actually are. The world is mobile-first, and a huge share of real workflows are app-only, ride-hailing, food delivery, mobile banking, two-factor prompts, creator tools, regional super-apps. A browser agent can't install an APK, respond to a push notification, read an SMS one-time code, use the camera, or drive a native app that never ships a web build. A phone can. And there's a second reason: fidelity. When an agent operates the same app a customer uses, you're automating the real thing, not a mock, not some undocumented internal endpoint that breaks next release. How it works A mobile AI agent runs a perception-decision-action (PDA) loop against the device. The agent builds its understanding from two sources. First, the accessibility tree, the structured hierarchy of on-screen elements the OS exposes for screen readers, which gives precise, machine-readable targets. Second, vision, a screenshot passed to a multimodal model for anything the tree misses, canvas UIs, games, custom widgets. Together, the tree gives coordinates and vision gives context. The agent gets a goal in natural language, reasons about the current screen, picks the next action, and e

2026-08-28 原文 →
AI 资讯

PostgreSQL Multi-Tenancy: Isolation That Survives a Growing Team

Startups building B2B products reach for multi-tenancy in PostgreSQL the same way on day one: one shared database, one set of tables, and a tenant_id column marking who owns each row. That is the correct call, and it stays correct for a long time. However, when that column is enforced by application code rather than by the database, a single forgotten predicate stops being a bug and becomes a disclosure event, and a disclosure event is one of the very few engineering failures that lands straight on your balance sheet as stalled enterprise deals, an unplanned legal bill, and a security review you can no longer pass. By understanding what multi-tenancy actually guarantees, which isolation model fits your stage, and how Row-Level Security moves that guarantee out of your codebase, startup CTOs and Fractional CTOs can make the tenant boundary hold without slowing the team down. (If you want to skip the theory, jump straight to the connection pooler trap that switches Row-Level Security off in production, what it costs in query performance, or when it is genuinely time to leave the shared schema.) Because "enforced by application code" means something very specific in practice. It means a promise that everyone will remember to filter on tenant_id , and that promise is the single most expensive line of undocumented policy in your entire codebase, because it holds perfectly for about fourteen months, right up until the afternoon a tired engineer ships a reporting endpoint that joins four tables and forgets the predicate on exactly one of them, and then a customer opens a dashboard and sees somebody else's invoices. That is not a bug. A bug is something you fix on Monday. A cross-tenant data leak is a disclosure event, which means legal gets involved, your enterprise prospects get an email from their own security team, and the deal that was supposed to close your Series A quietly moves to next quarter and then to never. The uncomfortable part is that this is not a story abo

2026-08-28 原文 →
AI 资讯

How I Built a Wedding Planning Suite with Supabase in 3 Months

How I Built a Wedding Planning Suite with Supabase in 3 Months Quick Answer: I built a full wedding planning platform in 90 days using Supabase as the backend (PostgreSQL database, real-time subscriptions, Row Level Security, and OAuth auth), Next.js 14 for the frontend, and a few carefully chosen npm packages for specific features like QR code scanning. The key was leveraging Supabase's managed services to avoid building auth, websockets, and file storage from scratch. Introduction Three months ago, I had an idea: what if couples could plan their entire wedding through one cohesive platform? Not a static checklist app, but a living, breathing system where vendors, guests, budgets, and timelines all talked to each other in real time. I'm a solo developer with a day job. I didn't have a team of backend engineers to build authentication, real-time sync, or file storage infrastructure. I needed a stack that would let me ship fast without shipping broken. Enter Supabase. I'd heard the "Firebase alternative" pitch before, but what I discovered was something far more powerful for developers who actually want to own their data and their SQL. This is the story of how I built WedPlanner—a full wedding planning suite—with Supabase, Next.js, and a few other tools. No VC funding. No offshore team. Just me, a tight deadline, and a PostgreSQL database that never let me down. Why Supabase? The Architecture Decision That Made Everything Possible When you're building alone, every architectural decision compounds. Pick the wrong database, and you'll spend weeks fighting migrations. Pick the wrong auth solution, and you'll ship with security holes you don't even know about. I evaluated Firebase, PlanetScale, Clerk, and rolling my own PostgreSQL on RDS. Here's why Supabase won: PostgreSQL, not a proprietary document store. Wedding data is relational. A guest belongs to a wedding. A vendor has multiple bookings. A budget category has many line items. Trying to model this in Firestore's

2026-08-28 原文 →
AI 资讯

Simple Hosted Metrics Dashboard API Explained (for Small Node.js SaaS with Postgres)

Choice Setup burden Incident evidence Best fit Hosted metrics API Low Good if event context is preserved Small teams with an on-call rotation Postgres plus a custom dashboard Medium Excellent for joining metrics to business records Low-volume systems with strong SQL skills Self-hosted metrics stack High Configurable, but operationally demanding Teams that already run observability infrastructure Short answer: start with a hosted metrics dashboard API, send a small set of custom application metrics from Node.js, and retain reconstruction fields in Postgres. Choose the custom Postgres path when joins are the investigation, or self-hosting when data control outweighs maintenance. That recommendation has a catch. A chart can show when enrollment failures rose, but it cannot explain which course, release, region, or feature state produced them unless those dimensions were recorded at write time. For an edtech SaaS, the real deliverable isn't a pretty dashboard. It is enough evidence to replay the story of a customer incident without guessing. How can Node.js send custom app metrics to a hosted dashboard API? Capture the dimensions an investigator can act on: metric name, timestamp, deployment identifier, region, tenant or school identifier, operation, outcome, and a bounded error class. Keep direct student data out of labels. A useful event might say that lesson_publish failed validation in the EU region on deployment 7f3c2a1 ; it should not contain a learner's name, email, answer, or free-form support message. Small is good. Stop there. Start with service-level signals tied to customer work: request count, failure count, latency distribution, queue depth, and the age of the oldest queued job. Add business-flow counters such as course publication attempts only when they answer a concrete incident question. Don't export every database column as a label. High-cardinality dimensions make charts harder to read, alerts harder to tune, and the ingestion boundary harder to reas

2026-08-28 原文 →
AI 资讯

How I Cut a Client's AI API Bill from Rs 85,000 to Rs 12,000 a Month

₹85,000 per month. That was the AI API bill sitting in my client's inbox when they called me in a mild panic last quarter. They run a mid-sized e-commerce operation in Pune — about 4,000 orders a day — and had integrated AI into customer support, product descriptions, and internal reporting. The AI was working beautifully. The invoice was not. Three weeks later, their monthly bill was ₹12,400. Same tasks. Same quality. No corners cut. Here's exactly what changed. The real problem: every task was using the most expensive model When I audited their setup, the issue was obvious within five minutes. Every single API call — whether it was classifying a customer complaint into one of 8 categories or generating a 2,000-word product description — was hitting the same premium model. It's the most common mistake I see with businesses adopting AI: they pick one model during the proof-of-concept phase and never revisit that decision as they scale. You wouldn't hire a senior chartered accountant to do data entry. But that's essentially what was happening — a top-tier reasoning model answering "Is this complaint about shipping or billing?" Fix 1: Model routing — the single biggest cost lever Model routing means sending each task to the cheapest model that can handle it at acceptable quality. I categorised their ~47 distinct API call types into three tiers. 68% of calls moved to the lightweight tier, 20% to mid-tier, only 12% stayed on premium. That single change dropped the bill from ₹85K to roughly ₹38K — no quality loss, verified with two weeks of A/B testing on customer satisfaction scores before switching fully. Fix 2: Prompt caching — stop paying for the same context twice Their support bot sent the same 1,200-token system prompt with every call — policies, tone, catalogue context, all identical across thousands of daily calls. Caching processes it once and references it cheaply on subsequent calls within the window. At ~6,000 support interactions a day, this alone saved ₹8,

2026-08-28 原文 →