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

标签:#TL

找到 139 篇相关文章

AI 资讯

Stop saying SSL: TLS only does three jobs, and your 'SSL cert' is usually not the outage

Runbooks still say "renew the SSL certificate" when the browser warning is obsolete protocol . The certificate can be brand new. The tunnel is still TLS 1.0. This is a shortened English note. The tables, handshake diagram, and OpenSSL CLI checks live on the original post: https://sunshout.tistory.com/2206 SSL vs TLS (the only distinction that matters) SSL is a Netscape protocol from the 1990s. SSL 3.0 is withdrawn (POODLE and friends). What every browser speaks now is TLS , currently 1.2 or 1.3. People still say "SSL cert" because vendors sold that phrase. The file is an X.509 certificate. The handshake that uses it is TLS. SSL TLS Who Netscape IETF Versions you might still see 2.0 / 3.0 (disable) 1.0 / 1.1 (disable), 1.2 / 1.3 (use) Status Forbidden Required If a ticket says "SSL is broken", translate it to: which TLS version did the handshake negotiate, and which cipher? The tunnel only has three jobs Confidentiality — encryption so a tap does not yield plaintext. Integrity — a MAC (today: AEAD) so a MITM cannot flip bits unnoticed. Authentication — the certificate binds this hostname to a key a CA will vouch for. https is that tunnel. It is not "the lock icon means the page is safe to click." It means the bits on the wire are for that name, encrypted, and unmodified. XSS and a malicious origin are a different layer. The outage that is not the certificate Symptom: new Let's Encrypt leaf, browsers still scream obsolete TLS or refuse the handshake on phones. Cause: nginx/Apache/openssl still allow TLS 1.0/1.1, or the server has no 1.2+. Renewing the cert does nothing. Check, do not guess: # must fail openssl s_client -connect example.com:443 -tls1 # must work openssl s_client -connect example.com:443 -tls1_2 nginx: ssl_protocols TLSv1.2 TLSv1.3 ; ssl_prefer_server_ciphers off ; Keep TLS 1.2 next to 1.3 if you still have old Android or old Java. New services can prefer 1.3. What to put in the cipher line Key exchange: ECDHE (forward secrecy). Static RSA key exchange

2026-08-25 原文 →
AI 资讯

Building a Plug-and-Play JVM Compiler for Android and Desktop with Bytesmith

What if adding Kotlin and Java compilation to your application didn't mean building an entire compilation pipeline yourself? What if you could add Bytesmith, configure the filesystem once, provide your source files and output destination, and simply compile? That's the idea behind Bytesmith . Bytesmith is a Kotlin and Java compiler toolkit designed for JVM and Android applications. It provides a unified API for Kotlin, Java, and mixed-language compilation, while also supporting filesystem abstraction, custom classpaths, boot classpaths, compiler plugins, packaging, and diagnostics. Configure the environment, provide the source, specify the output, and compile. The problem Compiler tooling can become surprisingly difficult when it is tightly coupled to the environment in which it was originally designed to run. You might need to deal with: Kotlin compiler versions Kotlin standard libraries Java compilation Bootclasspath configuration Dependency classpaths Source discovery Output handling Android storage Storage Access Framework URIs Packaging Compiler diagnostics And then there is the question of where those files actually live. On a desktop JVM, you might have traditional filesystem paths: /home/user/project/src/Main.kt On Android, you might be working with application storage or files selected through the Storage Access Framework: content://... If your compiler API directly depends on java.io.File , your compilation code becomes coupled to one filesystem model. Bytesmith takes a different approach. Adding Bytesmith The goal is to make compilation something you can plug into an application. With Gradle: implementation ( "io.github.sifisofakude.bytesmith:bytesmith-common:1.0.0" ) After adding Bytesmith, configure the filesystem your application wants to use. For a JVM application: FileSystems . current = JvmFileSystem () For Android: FileSystems . current = AndroidSafFileSystem ( context ) Once the filesystem is configured, the rest of the compilation layer can opera

2026-08-24 原文 →
AI 资讯

Architecting a background-service-based sound manager that survives Android's Doze mode

It was the final ten minutes of a high-stakes client presentation. I was mid-sentence, explaining a complex system migration, when my phone erupted with a loud, aggressive ringtone. The room went silent, but my phone did not. I scrambled to silence it, accidentally hitting the volume buttons while fumbling with the screen. That moment of pure, unadulterated embarrassment followed me for days. It was not the first time this had happened, but it was the time I decided I had finally had enough of relying on my own memory to toggle sound profiles before entering sensitive environments. Most of us live in a state of perpetual concern regarding our devices. We walk into movie theaters, attend religious services, or sit through medical consultations, constantly checking our pockets to ensure we have toggled the mute switch. If we forget, we face the social friction of a disruption. The existing solutions were either too manual—requiring a conscious effort I rarely possessed in the moment—or too intrusive, demanding constant location permissions and draining the battery to perform simple state changes. I wanted something that functioned as a set-and-forget background utility. I needed a system that understood the context of my environment without requiring me to interact with an interface every time my routine shifted. To build this, I had to architect a background service that could survive the aggressive power-management constraints of modern Android, specifically Doze mode. The primary challenge was ensuring that my sound-toggling logic fired precisely when a rule was triggered, even if the device had been sitting idle for hours. I initially experimented with a standard Service , but Android’s lifecycle management quickly killed it to save resources. I shifted to using a ForegroundService with a persistent notification, which is the standard approach for long-running tasks, but that only solved the visibility part. The real hurdle was the timing accuracy required for eve

2026-08-24 原文 →
AI 资讯

Atlassian Now Trains Its AI on Your Work by Default — and Full Opt-Out Is an Enterprise Feature

If you run a team on Jira or Confluence, the deal changed on 17 August and the change was opt-out. From that date, by Atlassian’s own account, the content your team writes into its Cloud products — Confluence pages, Jira tickets, the descriptions and comments where the actual work lives — is used by default to train Rovo, Atlassian’s AI assistant. You were not asked to opt in. You were, at best, given a switch and left to find it. Answer first, because the detail matters more than the outrage: there are two settings, and they are not equal. One governs your in-app data — the text itself. The other governs metadata — the derived signals about that text. On the Free, Standard and Premium plans you can turn off the content, but the metadata switch is greyed out; Atlassian’s support page reads, flatly, “You can’t change this setting.” The full off switch, the one that also stops metadata contribution, is available only on Enterprise. Privacy, in other words, is now a plan tier. What actually changed, with the switches named Atlassian’s data-contribution documentation lays out a matrix that is worth reading slowly, because the defaults are doing the heavy lifting. In-app data contribution defaults to on for Free and Standard customers and off for Premium and Enterprise. Every tier can toggle that one. Metadata contribution is a different story: it is on across the board and can only be switched off by Enterprise. So the customer contributing the most by default — content and metadata, both on, no ability to fully stop it — is the one on the cheapest plan who never opened the settings page. The categories are broad. In-app data, per Atlassian’s materials, covers Confluence page titles and body text, Jira work-item titles, descriptions and comments, and custom status and workflow names. Metadata covers the derived layer: readability scores, task classifications (that a ticket is “sales work,” say), story points, sprint end dates, SLA values, and semantic-similarity measure

2026-08-24 原文 →
AI 资讯

Architecting Location-Aware Automation Without Killing the Battery

It happened during a quiet, solemn moment at a funeral. I felt the vibration in my pocket, and for a split second, I panicked. I had silenced my phone before entering, but I had accidentally toggled it back to normal mode while checking an email earlier that morning. In that room, the sound of a notification ping felt like a gunshot. The embarrassment was immediate and visceral. It was a clear signal that I needed a better way to manage my device's sound profile, a system that didn't rely on my flawed human memory. We live in an era of hyper-connectivity, yet our phones are surprisingly dumb when it comes to context awareness. I found myself constantly manually adjusting volume sliders. Meetings, gym sessions, prayer times, movie theaters—the list of places requiring silence is endless. Most existing solutions were either too heavy, requiring complex IFTTT integrations that lagged, or they were privacy-invasive, requiring constant cloud syncing. I wanted something that lived locally on my device, respected my data privacy, and didn't turn my phone into a brick by noon. The core problem wasn't just the silencing; it was the cognitive load of having to remember to revert those changes, which is how you end up missing important calls for the rest of the day. To build Muffle, I had to solve the geofencing puzzle. The temptation for any Android developer is to fire up a LocationRequest with high-accuracy settings and just poll the GPS coordinates. That is the fastest way to destroy battery life and get your app killed by the Android system's battery optimizations. Instead, I leaned into the GeofencingClient API. It is designed precisely for this use case: it lets the system handle the heavy lifting of location monitoring at the hardware level, rather than keeping the radio awake in my application process. I configured the GeofencingRequest using GEOFENCE_TRANSITION_ENTER and GEOFENCE_TRANSITION_EXIT triggers. The magic happens in the PendingIntent that gets fired when th

2026-08-23 原文 →
AI 资讯

My performance optimization silently disabled the feature the app exists for

This is a submission for DEV's Summer Bug Smash : Smash Stories. TL;DR. I bounded a database read to make my analyzer faster. I derived the bound carefully, wrote the reasoning into the KDoc, and shipped it behind five passing tests. The bound was wrong in a way none of those tests could see. The result: if a lifter deloaded once in the middle of a stall, which is the correct thing for a lifter to do, my app stopped telling them they had plateaued. No crash. No error. No log line. The feature just quietly stopped being true for the people using the app correctly. The setup WhyRep analyzes your training rather than just recording it. The core promise is that it tells you when you have stalled and what to change about it, and that every verdict traces back to a methodology document rather than to something a language model made up. The architecture decision underneath that promise is that nothing is precomputed . Verdicts are derived from raw set logs on read, every time, so there is no cached judgement to go stale when the rules change. Which means every read walked the lifter's entire history for every exercise in the session. That is fine at ten sessions. It is not fine at three hundred. The obvious optimization is to bound the read. The obvious bound is "it only needs the last two weeks." That was my first wrong answer, and it is worth thirty seconds before I get to the interesting one. The plateau rules are not measured in calendar time. They are consecutive-miss counts, and the count varies by lifter tier and by whether the movement is a big or small joint action. The widest window in the signed methodology is an elite lifter on a small joint action: 14 consecutive sessions without progress. Train a lateral raise once a week and 14 sessions is over three months of data. A 14-day cutoff could never have fired a plateau for anyone above beginner tier. It would not have thrown. It would have quietly stopped detecting the exact thing the product exists to detect. Th

2026-08-23 原文 →
AI 资讯

You Benchmarked the Model. Now Benchmark the Server.

You picked a free model because the answers looked good. Good answers are not an endpoint. An endpoint is the model plus the server plus the network. Demos pass. Pipelines stall. The model was rarely the problem. So why do we keep benchmarking only the model? Because it is easy. You paste a prompt. You read the output. You declare a winner. The server never gets a vote. This post is a reproducible benchmark. It measures the pair, not the model. Run it before you wire any free endpoint into CI. The Pair, Not the Model Most evaluations compare answers. You paste a prompt. You judge the output. You pick a winner. That measures the model. It ignores the server. Free model access usually means a shared endpoint. A free server option means shared tenancy. Other users share the CPU, memory, and network. Your latency is their latency. Your timeout is their timeout. Here is the scenario I keep seeing. A team evaluates a free model on Friday. The answers look great. They wire it into CI on Monday. By Wednesday, the pipeline is red. The model did not change. The server did. A neighbor started a batch job. Now every request queues behind it. I applied the same harness to MonkeyCode's free model access and their free server option. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I did not trust the demo. I built a harness instead. The Harness A benchmark needs three things. A fixed prompt set. A concurrency ladder. A pass/fail table. Here is the harness I use. #!/usr/bin/env python3 """ Benchmark a model endpoint as a pair: model + server. """ import argparse import asyncio import json import statistics import time import httpx PROMPTS = [ " Say OK. " , " Classify this log line: ERROR disk full " , " Return one word: is 429 a retryable status? " , ] async def fire ( client , url , payload , sem , timeout = 30 ): async with sem : start = time . perf_counter () try : r = await client . post ( url , json = payload , timeout = timeout ) return r . sta

2026-08-20 原文 →
开发者

D-MO (Data Micro-Optimizer)

En el día a día del desarrollo de software y el análisis de datos, la preparación y limpieza de archivos financieros suele ser una de las tareas más repetitivas y propensas a errores. Tratar con layouts rígidos, filas desfasadas y nombres de columnas que cambian sin previo aviso genera una fricción operativa constante. Para resolver este problema de raíz—y manteniendo un enfoque estricto en la seguridad de la información—desarrollé D-MO (Data Micro-Optimizer) , una potente herramienta web de procesamiento ETL (Extract, Transform, Load) que corre completamente del lado del cliente. El Origen: Privacidad por Diseño Cuando manejamos reportes bancarios o información financiera sensible, subirlos a plataformas externas de conversión representa un riesgo crítico de seguridad. D-MO nació bajo la premisa de la privacidad absoluta: todo el procesamiento ocurre en la memoria local del navegador a través del cliente. Los datos estructurados jamás se envían a un servidor externo, eliminando latencias de red y garantizando un entorno de zero server overhead . Arquitectura del Pipeline (Flujo de Datos) El sistema procesa la información de manera secuencial a través de un flujo desacoplado, lo que permite transformar archivos complejos en datasets listos para producción en un solo clic: [ Archivo Local ] (.csv / .xlsx / .xlsb) │ ▼ ┌──────────────┐ │ DropZone │ ◄── Validación de Extensión y Tamaño └──────┬───────┘ │ (Buffer / Texto plano) ▼ ┌──────────────┐ │ File Parser │ ◄── Detección de delimitadores y headers dinámicos └──────┬───────┘ │ (JSON Normalizado) ▼ ┌──────────────┐ │ ETL Engine │ ◄── Reglas de Negocio, Mapeo de Alias y Filtros CUSTOM └──────┬───────┘ │ (Dataset Limpio) ▼ ┌──────────────┐ │ Export File │ ◄── Generación de reportes limpios listos └──────────────┘ Core Técnico y Capas del Sistema La aplicación está construida sobre Next.js 14 (App Router) y TypeScript , dividiendo su lógica interna en tres componentes principales: 1. Interfaz y Coordinación ( page.tsx )

2026-08-19 原文 →
AI 资讯

How to Replicate MySQL to BigQuery with Sling

How to Replicate MySQL to BigQuery with Sling Last updated: July 2026 Getting MySQL data into BigQuery usually means picking a tradeoff. Hand-rolled scripts are cheap to start and expensive to keep alive once schemas drift. Managed connectors are quick to set up but bill per row and put your pipeline behind someone else's control plane. Sling sits in between: a single binary, a few lines of YAML, and a load path that uses BigQuery's own bulk ingest underneath. This guide walks through a real replication, end to end. Everything below — the row counts, the timings, the type mapping — comes from an actual run against a MySQL 8.4 source and a live BigQuery dataset. You can reproduce it. Installation Sling is a single binary with no runtime dependencies. Install it however suits your setup: # macOS / Linux curl -fsSL https://slingdata.io/install.sh | bash # Windows irm https://slingdata.io/install.ps1 | iex # Python pip install sling Confirm it's on your path: sling --version Connection setup Sling needs two connections: the MySQL source and the BigQuery target. Both can be set with sling conns set , which writes them to ~/.sling/env.yaml . MySQL source sling conns set mysql_source type = mysql host = 127.0.0.1 port = 3306 \ user = root password = mypass database = demo Or with a connection string: sling conns set mysql_source url = "mysql://root:mypass@127.0.0.1:3306/demo" BigQuery target BigQuery authenticates with a service-account key. The account needs BigQuery Data Editor and BigQuery Job User on the target project. sling conns set bigquery_target type = bigquery \ project = my-project dataset = demo \ key_file = /path/to/service-account.json If you have a Google Cloud Storage bucket handy, add gc_bucket=my-bucket . Sling will stage batches there and trigger a BigQuery load job from GCS, which is the fastest bulk path. Without a bucket, Sling stages locally and still loads in bulk — that's the setup used for every number in this guide. Test both connections sling c

2026-08-18 原文 →
AI 资讯

Mongodb Partitioning

At Whoz , we build a SaaS platform that helps professional services companies manage their talent staffing. At the heart of our product lies a concept called a worklog — a record of time spent by a user on a given activity. Every consultant, every day, on every project, generates worklogs. It sounds simple. And for years, it was. Then the numbers caught up with us. The Problem: A Collection That Never Stops Growing Our worklog MongoDB collection had reached 530 million documents , representing just over 32 GB of data. And the growth rate was accelerating — not just because we were onboarding more clients, but because users were increasingly splitting their activity into finer-grained entries, generating more worklogs per person per day than ever before. A worklog document looks roughly like this: { "date" : "2024-03-15" , "talentId" : "abc123" , "workspaceId" : "ws456" , "duration" : 0.5 , "activityType" : "TASK" , "taskId" : "task789" } Simple enough. But at 530 million of them, even the most routine operations become painful: Backup : nearly 1 hour Restore : up to 4 hours Schema migrations : we hadn't dared run one at full scale yet — and that alone was a warning sign Every year, the collection grows faster than the year before. The backup and restore windows were becoming operationally risky. We needed to act. Exploring Our Options We identified three potential approaches before settling on a solution. Option 1 — MongoDB Sharding Sharding is MongoDB's native horizontal scaling mechanism. It distributes a collection across multiple shards, each backed by its own replica set. On paper, it looked like a match. In practice, we ran into a fundamental mismatch with our actual needs. Our core issue wasn't query throughput — worklogs from three years ago are rarely queried, and when they are, performance expectations are low. Our issue was operational overhead : backup time, restore time, and the cost of running large batch operations over the full dataset. Sharding woul

2026-08-18 原文 →
AI 资讯

Architecting a Low-Power Geofencing Engine: Lessons from Battery Optimization on Android

Opening hook The silence in the room was absolute, save for the rhythmic scratching of pens against paper during a final exam. I was three rows back, feeling confident, until my phone decided to vibrate against the wooden desk. It wasn't a subtle hum; it was a rhythmic, aggressive buzz that echoed like a snare drum in a cathedral. Every single head turned in my direction. I scrambled to silence the device, but in my panic, I fumbled the power button. That moment of pure, unadulterated embarrassment was the catalyst for everything I have built since. The problem We live in an age where our devices are supposed to be smart, yet they consistently fail at the most basic context-aware tasks. We have high-end processors, sophisticated neural engines, and sophisticated sensor arrays, but we still have to manually toggle a 'silent' switch before entering a meeting, a lecture, or a mosque. The friction isn't just the act of flipping a switch; it is the cognitive load of remembering to do it and, more importantly, remembering to turn it back on afterward. I spent months living with the anxiety of a phone that might ring at the worst possible time. I tried existing automation tools, but they were either bloated, relied on cloud-based tracking that hammered my battery, or lacked the granular control I needed for specific locations. Most apps that promised location-based sound management were either imprecise or drained my battery by keeping the GPS radio active around the clock. I didn't want a heavy-duty tracking app; I wanted a silent, background-native utility that respected the hardware constraints of the Android platform while solving the specific problem of environmental sound management. The technical decision / implementation When I started building Muffle, my primary constraint was the battery. Android users are rightfully protective of their background processes, and if my app showed up as a primary battery consumer in settings, it was effectively useless. I had to de

2026-08-18 原文 →
AI 资讯

Architecting a Low-Power Geofencing Engine for Android Background Services

Opening hook It happened during a quiet Friday Jumu'ah prayer. The imam had just reached the most solemn part of the khutbah when a high-pitched, insistent ringtone echoed through the entire hall. Heads turned, whispers started, and the person responsible scrambled to silence their device, only to fumble and drop it in their haste. I sat there, mortified for them, knowing exactly how that sinking feeling felt. It is the universal experience of the modern digital age: the gap between our intentions to be polite and our actual ability to manage our phone's state in public spaces. The problem We live in a world of constant notification, yet we lack a standard way to govern our devices based on our physical context. Android provides AudioManager and NotificationManager , but these are reactive tools that require manual input. I tried using standard alarm-based triggers, but they lacked the spatial awareness I needed. If I am at the office, I want my phone on vibrate. If I am at home, I want it back to normal. If I am at a medical clinic, I need it on silent. Most existing solutions rely on heavy GPS polling, which drains the battery within hours. They treat location services as a raw stream of coordinate data rather than a state-based trigger. I wanted something that functioned entirely in the background, survived system reboots, and operated without a constant drain on the user's battery life. The friction wasn't just about silence; it was about the cognitive load of having to remember to switch profiles. I wanted my phone to handle the context switching for me, autonomously and reliably, without becoming a battery-draining nightmare. The technical decision / implementation To solve this, I moved away from manual polling and adopted the GeofencingClient within the Google Play Services location APIs. The decision to use this over raw LocationManager updates was rooted in battery efficiency. The GeofencingClient pushes the heavy lifting to the OS level. It uses a combina

2026-08-16 原文 →
AI 资讯

Stop Wasting Free Model Calls on Trivial Diffs: A Three-Tier Escalation Ladder

A merge request changes one README line. The pipeline still calls a model. It costs tokens. It adds latency. It tells you almost nothing. Sound familiar? If you maintain a small CI setup, this failure keeps showing up. The instinct is to put model-based review everywhere. Then the free tier dies in a week. The fix isn't another monitor. It's a small decision gate that decides whether a diff deserves a model call at all. The operator-supplied availability claims for MonkeyCode include free model access and a free server option. I treat those claims as a starting point, not a quota guarantee. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Why every diff shouldn't hit the model Free model access is not infinite. Even if it feels free, there are hidden ceilings. Free tiers often cap requests, tokens, or time-based windows. Model output variance on trivial diffs adds noise, not signal. CI latency grows. A two-second call across a hundred merge requests is real time. The highest-value model review is rare, not constant. If you call a model on every change, you pay the full cost while getting almost none of the benefit. The gate is supposed to fix that. A three-tier escalation ladder I use a small decision table. It doesn't need to be perfect. It needs to be boring and predictable. Tier Trigger Action Model call? 0 Up to 50 added+removed lines, only docs or config suffixes, no sensitive paths Run lint and skip the model No 1 Code or test files touched, 51–400 lines, no lockfile, no migration, no sensitive path Send one bounded prompt to the free model Yes, once 2 Over 400 lines, new lockfile, migration, auth or secret paths Require human review first. Use a model only to summarize, not to decide Optional The exact numbers are arbitrary. They matter less than the fact that tier 0 never reaches the model. The code Here is a plain Python gate. It reads simple diff stats and changed paths. from pathlib import Path DOC_OR_CONFIG = { ' .md ' , '

2026-08-15 原文 →
AI 资讯

Make Free Model CI Jobs Replayable Before You Retry Them

The retry trap A free model CI job fails on a timeout. You click retry. The whole pipeline starts over: checkout, build, dependencies, model call. That is the trap. Why re-run the world for one timeout? Retrying the pipeline does not isolate the flaky step. It makes a small problem expensive. I wanted a workflow that replays just the model call, not the whole pipeline. So I made every free model call leave behind a tiny reproducible record. A record has two halves: the input envelope and the output hash. If the job fails, I can replay the input against the same model and compare the output hash. No full pipeline re-run. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I use MonkeyCode's free model access for the model step and its free server option as a small replay store. I do not assume exact quotas, model names, or availability windows here. The pattern works with any free HTTP model endpoint and any tiny key-value store or CI artifact. Why a hash and not the full prompt Full prompt logs are useful until they are not. A free model job may receive a snippet of a merge request, an error message, or an environment variable. Store the raw text in CI logs and you can accidentally leak source or secrets. Store a hash and the replay input in a locked artifact, and the risk drops. A hash also gives me one cheap comparison target. I do not need to reason about the entire response to see that an endpoint changed. I only need byte-level equality. The record shape For every model call, I save the fields below. request_id: a hash derived from model, prompt hash, and a timestamp. prompt_hash: the hash of the normalized prompt. response_hash: the hash of the raw response. status: the HTTP status of the original call. bytes: the length of the response. The exact hash algorithm matters less than using the same one on both sides. I use SHA-256 because it is available everywhere. GitLab CI wiring I run two jobs. The first job calls the model and post

2026-08-15 原文 →
AI 资讯

Building a Zero-Cloud Android Service: Privacy by Architecture

It happened during a quiet Friday sermon at the local masjid. The room was dense with silence, the kind that feels heavy and intentional. Suddenly, a jarring ringtone shattered the atmosphere—someone’s phone, vibrating against the hardwood floor. It wasn't my phone, but the collective wince of the entire room was visceral. A hundred people stopped mid-thought, turning their heads toward the source of the noise. I sat there, my own phone tucked in my pocket, realizing that I had almost been that person just a week prior. It was a moment of pure, avoidable human friction. We live in an age where our devices are supposed to be smart, yet they consistently fail at the most basic context-awareness. I found myself manually toggling my sound profile before every meeting, lecture, or appointment. It is a recurring cognitive tax. If I remembered, great. If I forgot, I risked social embarrassment. Even worse, once the meeting ended, I would inevitably leave my phone on silent for the rest of the day, missing important calls from family or clients. Existing solutions often felt like overkill—they required account creation, constant background sync to a cloud server, or permissions that felt invasive for a task as simple as changing a volume setting. I wanted something that lived entirely on the device, functioning as a silent, invisible utility that didn't need to 'phone home' to function. When I started building Muffle, I decided early on that the entire architecture would be zero-cloud. This wasn't just a philosophical choice; it was a technical constraint I imposed to ensure the app remained performant and trustworthy. By forcing myself to avoid backend dependencies, I had to rely heavily on Android’s AlarmManager and ForegroundService patterns. The biggest challenge was the 'Prayer Time' trigger. Most developers would reach for a Firebase Cloud Function to calculate these times based on the user's location. Instead, I integrated the Adhan library locally. I had to handle c

2026-08-15 原文 →
AI 资讯

0 of 3 Articles Published for 3 Days Straight: The 41-Second Timeout Margin That Killed My Automation

For three mornings in a row, my audit log printed the same line: published today: 0 / target: 3 . Nothing crashed. The scripts ran, exited, and produced nothing. The entire cause turned out to be a 41-second margin — a 300-second timeout against a process that actually takes 259 seconds. Changing one number to 600 turned 0/3 into 3/3 the next morning. Some background: I went from earning 100k yen a month as a university student to 600k a month juggling multiple gigs, then lost all of it overnight to a company-initiated layoff. Over the following six months I built an autonomous Claude Code environment, and I'm now above 1.2M yen in monthly revenue. At the core of it is a system that publishes three affiliate articles every morning without a human touching anything. Why this system works The difference between people who keep earning from affiliate marketing and people who drop out is not writing skill, and not a nose for picking products. It's whether you can keep going . Articles that tend to earn on Rakuten Affiliate share a common pattern: spec-comparison articles about home appliances and gadgets priced above 50,000 yen, with lots of reviews and in stock. Robot vacuums, portable power stations, heat-pump washer-dryers, fully automatic coffee makers. The search intent is "I want to compare before I buy," so product link click-through is high and it fits the structure of affiliate marketing well. The problem is cost. Researching the specs of a high-ticket appliance on the web, building a comparison table, and finishing an article good enough to include the "honestly weak points" section takes 30 to 40 minutes. Three articles is close to two hours. Almost nobody has the willpower to repeat that 365 days a year. I don't either. What you need here isn't "trying harder" — it's an environment that keeps running even when you don't try hard . Once the system is built, the running cost is just API calls. The affiliate-factory I built is a simple structure made of four sh

2026-08-15 原文 →
AI 资讯

Who’s Tracking You? Use This New Service to Find Out

It can be daunting to determine who's responsible for showing ads on the websites we visit, or who's harvesting data from the mobile apps we use every day. That information is already semi-public, but it is not easily parsed and traditionally much of it has remained walled away in the hands of large advertising platforms. Not anymore: A powerful and free new service called DecryptAds scrapes and correlates this adtech data and makes it simple to quickly learn a great deal about the entities that are tracking you.

2026-08-14 原文 →
AI 资讯

GitLab CE Comes Without a Runner: Why Nothing Executes Your Pipelines

You installed GitLab Community Edition, pushed a .gitlab-ci.yml , and watched the pipeline sit at pending until it went grey. No error, no failed job, nothing in the logs worth reading. Nothing is broken. Your instance has no runners, and it never had any. Why a fresh instance has none GitLab is two things that people assume are one thing. There is the application: repositories, issues, merge requests, the CI/CD system that reads your .gitlab-ci.yml and builds a pipeline out of it. And there is GitLab Runner: a separate program, on a separate machine, that actually executes jobs. The Omnibus package installs the first. It does not install the second, and it does not come with any machines to run it on. The confusion comes from GitLab.com, where shared runners are switched on by default and most people's first experience of CI is that it simply works. That shared fleet is hardware GitLab owns and operates as part of their hosted service. It is not part of the software you downloaded, so it does not come across when you run your own instance. So on a self-managed install, GitLab will happily accept your pipeline definition, parse it, create the jobs, and queue them. Then it waits for a runner to ask for work. If no runner ever asks, the jobs wait indefinitely. Confirming it in thirty seconds Go to Admin Area → CI/CD → Runners on your instance. If the list is empty, that is your answer. For a single project, Settings → CI/CD → Runners shows the same thing scoped narrower. A fresh instance shows nothing in either place. From the command line on the GitLab server: sudo gitlab-rails runner "puts Ci::Runner.count" If that prints 0 , no runner has ever been registered against this instance. One thing worth ruling out at the same time: a job can also sit pending when runners do exist but none of them match the job's tags. If your runner list is not empty, check whether your jobs specify tags: that no runner carries. That is a different problem with a different fix, and it is

2026-08-13 原文 →