More thoughts on Apple’s New Child-Protection Features #
I’m glad that Apple is doing something, and that their solution doesn’t make it easy to get around the new protections by default—like Facebook’s encryption option. Ben Thompson makes a good point: maybe it would have been better not to compromise the device, and do the scanning in iCloud (which parents could choose to enable). #
If you don’t use iCloud, then the safety vouchers are never sent anywhere. In that case—from a privacy standpoint—how is on-device fingerprinting different from fingerprinting in iCloud? It seems to be roughly equivalent. If Apple does enable end-to-end encryption in the future, I think their on-device approach makes a lot of sense and is better than fingerprinting in the cloud—which would rule out end-to-end encryption entirely.
In either case, the point of the CSAM detection feature is to detect the content if it’s stored in the cloud—not necessary when it’s shared. It doesn’t seem that Apple will detect or report CSAM in Messages, but they potentially could with the on-device scanning approach, and it would be the only way since Messages are already end-to-end encrypted.
“I’m the kind of person who takes pride in admitting when I’m wrong.”
A good way to think in general.
Give people the option to have flexible work schedules with performance goals, and let them have side projects so they don’t have to lie to you.
Apple's New Child-Protection Features
A few key points on image detection/reporting:
Detection happens on your device, not in iCloud
Cryptographic hashes of each images are compared with a database of known images only
The metadata is uploaded with each photo, and that’s what Apple uses to report potential abuse
A few key points on new parental controls in Messages:
Apple uses on-device machine learning to detect nudity
The user/child is given the option not to look at and/or distribute the image first
For accounts of children 12 and under, the parent can be notified if their child decides to proceed
This is one of those incredibly murky issues that do not have clear answers. It’s a tradeoff between protecting children and protecting privacy. Ignoring either enables terrible outcomes—on the one hand by sexual predators, on the other by abusive governments.
Ben Thompson of Stratechery thinks that Apple made a mistake in their approach because they violated the assumption that the user owns their device; a better tradeoff would be to scan in iCloud, similar to how Facebook scans images uploaded to their servers.
As far as I know, Facebook cannot scan images in Messenger when end-to-end encryption is enabled since the scanning happens in the cloud—not on the device.
Ben Thompson and John Gruber had a good conversation about Apple’s future privacy plans on a recent episode of Dithering (Podcast). They speculated that Apple’s decision to perform more work on-device (rather than in iCloud) could be laying the groundwork for enabling end-to-end encryption in iCloud in the future. Currently, iCloud backups are not encrypted, making them available to requests from law enforcement.
I’m glad that Apple is doing something, and that their solution doesn’t make it easy to get around the new protections by default—like Facebook’s encryption option. Ben Thompson makes a good point: maybe it would have been better not to compromise the device, and do the scanning in iCloud (which parents could choose to enable).
There were no rules at the start of the internet, but there were also few users, and the technology itself made it difficult for criminals to hide. It’s not the same place it once was. As in many societal debates, we need to find the right balance between safety and freedom.
From the kid’s perspective, I’m sure they’ll find creative ways to circumvent any censorship/controls their parents put in place. We don’t have to make it easy, though. Give them a challenge.
This is cool, Node.js added an experimental
--source-map-support flag in 12.12:
The stack traces were a bit wonky, though—the “->” prefix is not supported by most stack trace parsers (including Honeybadger).
>Error: oops, something went wrong at AppService.getHello (/Users/josh/tmp/test-node-app/dist/main.js:100:15) -> /Users/josh/tmp/test-node-app/dist/webpack:/test-node-app/src/app.service.ts:6:11 at AppController.getHello (/Users/josh/tmp/test-node-app/dist/main.js:68:32) -> /Users/josh/tmp/test-node-app/dist/webpack:/test-node-app/src/app.controller.ts:10:28 at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-execution-context.js:38:29 at InterceptorsConsumer.intercept (/Users/josh/tmp/test-node-app/node_modules/@nestjs/core/interceptors/interceptors-consumer.js:11:20) at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-execution-context.js:46:60 at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-proxy.js:9:23
That’s fixed in Node 14+, so the stack traces are supported everywhere.
>Error: oops, something went wrong at AppService.getHello (webpack://test-node-app/src/app.service.ts:6:11) at AppController.getHello (webpack://test-node-app/src/app.controller.ts:10:28) at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-execution-context.js:38:29 at InterceptorsConsumer.intercept (/Users/josh/tmp/test-node-app/node_modules/@nestjs/core/interceptors/interceptors-consumer.js:11:20) at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-execution-context.js:46:60 at /Users/josh/tmp/test-node-app/node_modules/@nestjs/core/router/router-proxy.js:9:23
Record PNW heatwave. High of 115 today.
Redfin is aggressively trying to sell me a house. I hope it’s not working.
On the bright side, my garage gym is now a hot yoga studio.
They say entrepreneurs are often irrational optimists.
Outliner wishlist for blogging
Here are some things I wish my outliner could do for an optimal blogging setup.
Custom block types
Roam gives you a few ways to view sub-elements: document, bulleted list, numbered list. I wish I could customize these/create additional types. Each type would have a custom stylesheet/template for display in the outliner, and associated attribute(s) in data exports (i.e. OPML, JSON, etc.).
This feature reminds me of early content management systems (which often had a single content/page type) and their successors—such as Expression Engine—which let you create custom content types. It opened up a lot of possibilities.
The key is that I want the ease of editing content in an outliner such as Roam, but greater flexibility when displaying it. The better the content in the outliner imitates the published display format, the less I have to think about formatting.
In the meantime, I wish Roam would actually include all of the display type metadata in JSON exports… (Currently it does not include the document display type.)
Imagine being able to see a live preview of content (sort of like markdown preview) in a right-sidebar.
Every block has a unique id
Roam has block refs, and they’re super handy since each element can have a true permalink. An alternative approach is to use the timestamp of when the block was created (maybe with millisecond precision)—however you would still have to store this with each block, which isn’t really practical if using markdown as the storage format.
Checking out PolyworkHQ. Added a few recent and not-so-recent work highlights so far. Follow me if ya want!
I might be onboarding the first junior developer to @honeybadgerapp’s open-source team. Pretty stoked about that. Been trying to think of ways to involve juniors in the business for a long time.
We don’t hire a lot of people full-time and our product development process isn’t great for mentorship. Open source is a different story, though. There are lots of small things to learn and do there, and it’s public, which helps build community.
My current plan is to bring juniors onto the team with few expectations. They can hang out to learn and contribute when they’re ready. We’ll see how it goes.
“I love that you are keeping the customers’ interests first.”
rails new test_app --minimal never fails me.
To anyone who subscribes to this RSS feed, sorry for the dump. Archiving some recent Twitter content.
It’s almost a specification maybe. We’ll flesh it out w/ deeper content in the near future. It uses Ruby pseudocode but applicable to most environments, I think.
Would anyone like to take a look and tell me if they find the content useful? Or lacking? :)
Hint (the consulting company I started before Honeybadger) is growing up, thanks to the hard work of my business partners @benjaminwood and @natron99. I’m really proud of them—it’s cool to see their vision evolve.
A goal that you should hold us to: “within three years each vertical (e.g., operations, sales, development) inside Hint will consist of at least 50% under-represented groups.”
That’s not about hitting a target; we want the business to represent more than ourselves. Colleagues with diverse backgrounds make us and our clients better.
We also have some strong opinions about contracting and the industry. Too many companies burn out their employees. We want to do the opposite—create a culture centered around work/life balance.
If you want to work on fun and challenging projects at a sustainable pace with people who support you, we’re hiring developers (100% remote, of course).
A national one-week vacation? lol, it takes me a week just to stop hyperventilating.
I finally found something that my M1 MacBook Air seems much slower to perform: optimizing png images w/ ImageOptim.app.
Ben is a compliance wizard.
With enough lies in your LinkedIn profile, cold sales emails are like a one-sided game of Mad Libs.
A brief overview of CRT for the uninformed. The book she recommends is also a good short read.
Parenting is fckn hard. Here’s to all the good parents out there. Also to the children of bad parents, complex parents, and everyone in between.
Here are some resources he recommended to me:
Modern outliners like Roam and logseq need a common interchange format. OPML seems like the natural choice? For instance, Workflowy has supported OPML since 2013.
Outliners, wikis, etc. have rich histories. It seems like one of the major contributions of modern “tools for thought” is to combine these concepts in interesting ways.
My blog takes 32 seconds to build on my M1 mac, assuming cached dependencies (and most of that time is doing a Roam export). The Netlify build is over 2 minutes. I wish it were more like 10 seconds total.
The local build would be < 10 seconds if I had direct access to an OPML or JSON feed. Maybe it’s time to reconsider Roam as a blog CMS.
“Christian faith has far too often become a weapon in the arsenal of those who worship at the altar of politics.” #Quotes
The term “Full Stack” was created before “modern” web development. It’s still useful for the original style of web development, IMO—e.g. the one where you own the full stack.
Underrated tool: Turn off retweets by @b0rk http://turn-off-retweets.glitch.me
We built Hook Relay to send webhooks to our own customers—we wanted better visibility into event deliveries, plus a robust backend for reliability and security concerns.
While our primary use case was outbound webhooks (great for SaaS companies who want to give their users limitless integration options), Hook Relay also does inbound! You can proxy your flaky 3rd-party services through Hook Relay to get instant retries, replay, and much more.
I know that’s rare, though. You never have errors.
I have since added this config to one of my other projects, honeybadger-io/honeybadger-webpack. In the process I replaced the markdown parsing code with the keepachangelog NPM package (which I hadn’t noticed before.) #
I also submitted a PR to contentful-labs/keepachangelog to add a feature to add a new release to the changelog. #
I’m now thinking about how to share our Ship.js config across repos to avoid duplication. It would be nice if Ship.js supported plugins that could implement alternative changelog formats and release steps. 🤔 #
Much of the most spirited conversations have centered on a pre-launch project called BitClout, a social crypto-exchange where users can buy and sell tokens based on people’s reputations. The app, which launches out of private beta tomorrow morning, has already courted plenty of controversy inside the crypto community, but it’s also amassed quite a war chest as investors pump tens of millions into its proprietary currency.
Oh right, that was a social credit system. This is more like social capitalism, so much better.
Heya is now free to use under the AGPL. https://www.heya.email/
🇺🇸 It’s nice to see thousands of people celebrating something positive. It’s been a while.
Extends Turbolinks to prefetch links on hover.
Looks similar to this gist that I currently use.
Day Week 🇺🇸
Twitter strikes again
I routinely block Twitter and other social media while on vacation. It’s a great way to reset. Having just returned from two weeks off, my Twitter habit is under control, and thus I find myself getting work done.
Just a little bit ago, by impulse—while waiting for the tests to pass—I opened Twitter. 10 minutes later I’m reading some guy’s blog post about why he’s a Christian Trump voter.
📄New blog post: Make Customer Support Your Competitive Advantage
📕 Book notes from Radical Candor by Kim Scott
I use and recommend Fathom Analytics for privacy-first, GDPR and CCPA-compliant website analytics. If you use this link to sign up, I’ll get a commission, and you’ll get a $10 discount on your first invoice.
Moved my Diet notes into my new public notes system.
Nice early voting reminder from HelpScout:
(Displayed after all support tickets have been responded to.)
Thoughts on Prepaying your mortgage #
Added more RSS feeds
(In the process I fixed some issues with my articles feed—sorry if you got some duplicate updates.)
test && commit || revert
test && commit || revert (TCR) is a new programming workflow introduced by Kent Beck in 2018. In a normal TDD (Test-driven Development) workflow, the goal is to write a failing test before writing the code to make it pass. TCR flips the TDD paradigm upside down, with a twist:
Not only must your tests always pass (on every file save, no less), but if they don’t pass, your code is automatically reverted.
I must admit: when I learned about TCR, I hated the idea. Coming from a TDD background, it’s so counter-intuitive. It’s funny, though, the more I think about my initial reaction, the more I want to try it.
A Honeybadger customer replied to one of my onboarding emails:
Another Honeybadger testimonial (emphasis added):
As far as how it compares to Sentry, I have had a great experience with Honeybadger. The UI is much much easier to navigate than Sentry. It is less cluttered, and gives me the information I need right away, all in one place. The setup in Elixir was so much easier than Sentry too! I haven’t explored all the options in Honeybadger yet, but I’m excited about uptime tracking as I’ve been using Pingdom for that, but I’d rather consolidate as many tools as I can.
Taking a break from FounderQuest for a few months. Don’t worry, we’ll be back for season 3 with fresh episodes (and fresh attitudes?) Time off is important, but I’m already looking forward to recording again. 🤙
Added permalinks on hover
Only H1 headings generate separate pages (instead of creating a page for every block). This is an alternate approach to a previous idea:
Added blockquote styles
There was an HN discussion about it late last year.
What a strange year.
Cobra Kai is an allegory of America, right?
My ideal work day
Or what I like best
I like to keep my head down,
making progress on challenging problems.
Not passively engaging on Twitter
It’s bad when the water cooler is attached to your desk
Working with people, yes—
but towards meaningful goals
really helping them move forward
…not shouting empty advice
I don’t want to be a thought leader
I just want to make cool stuff
In Federalist 84, Hamilton argues against the inclusion of a Bill of Rights in the Constitution (and a few other misc. things).
In Federalist 85, Hamilton concludes The Federalist Papers with an argument for ratifying the Constitution now and amending it later.
The framers knew that the Constitution wasn’t perfect, and they anticipated that there would be unknowns as the nation grows and develops. That’s why there’s an amendment process.
In Federalist 83—the last of a series of six essays on the judicial branch—Hamilton examines the constitutional provision for trial by jury in criminal cases.
In Federalist 82—the fifth of a series of six essays on the power and limitations of the judicial branch—Hamilton further discusses the jurisdiction between the State and Supreme Courts.
In Federalist 81, Hamilton examines the distribution of the judicial authority, including the role of the Supreme Court as an appellate court, its limited original jurisdiction, the inferior district courts, and the relation of the courts to State legislatures.
This was a weird day to lose RBG. What a career. RIP.
Hamilton continues his analysis of the powers and limitations of the judicial branch in Federalist 80.
Hey, it’s Constitution Day. How fitting. :)
TFW you deploy a change to a complex system and IT WORKS!!!
A listing of companies that don’t desperately email and call you constantly saying “Remember us! Please use our tools! Check us out! Hey hey hey!
No lifecycle emails. No sales calls. No contact with you outside of the product itself.
If you have the choice, write a book, teach a course, build an app… just don’t start an infrastructure monitoring company. 😂 Link
Currently Middleman builds a page for every Roam block (including nested blocks) in the export.
Being able to link directly to blocks is really nice if I want to write a short blog post in Daily Notes, for example, but then link to it on its own page. I.e., here’s this post.
I will rarely want to link to more than one or two levels deep, however. I could add a setting for that, so that it only generates pages N-blocks deep.
I could also add an option to skip creating pages for blocks without children.
In Federalist 78, Hamilton examines the judiciary.
I sent an email to my newsletter today that used a (humorous) hacked Trump tweet as an example of a link hijacking vulnerability. I only got two angry replies (not bad), but the click rate is more telling… So far 2.4% compared to the normal 4-10%.
The content itself is really interesting, so I’m thinking people have Trump fatigue. Come to think of it, so do I. Lesson learned moving forward. 😂
Throw away your todo lists
Alex tweeted about todo lists: “I don’t like todo lists because I don’t like being told what to do, even by past me.”
My favorite todo lists are the ones that are easy to throw away. It’s why I prefer 3x5 cards.
I also like contextualizing todos, which is something most apps do poorly. For instance, I write my home maintenance todos on a whiteboard in my garage.
In Federalist 77, Hamilton concludes an 11-part series of essays on the Executive branch.
Marketing should not be manipulative. Good marketing should stand on its own, and the user should be better for it regardless of whether they end up buying today. That rules out much of advertising. We do some advertising at Honeybadger, but try to direct it towards providing legitimate value to the audience, not just our users.
Started a Website todo list
To whoever needs to hear this: stop reading the Twitter feed.
This site is now deployed to Amazon S3
Netlify has been having issues for me lately; today, the
fetch-roam script I use to export my database when building this website began timing out, even though I’ve had no issues with it locally.
Build times have also been a problem. I can build this site in around 25 seconds on my 16” MacBook Pro, including the database download. Netlify was routinely taking 3-5 minutes—Ruby in particular seems to be very slow on Netlify.
So I deployed the site to s3 instead, which actually seems to fit this project better:
I can run deploys locally or via any CI system (I’m planning to use GitHub Actions)
aws s3 sync, so files which haven’t changed since the last build don’t need to be uploaded.
If I can figure out how to keep the build directory around between CI runs (using a shared volume, maybe?), Middleman generation may also run faster, as it skips unchanged files. This would sort of give me incremental builds.
I’m not totally sure on this one, since it does need to generate the file contents to know what changed.
Normally I’d miss some of the niceties that come with Netlify such as branch previews and functions, but in this case I think the tradeoff is worth it.
Fires rage across the West Coast. It feels like Chernobyl in the US rn.
“At least it’s not radioactive” pretty much sums up 2020 at this point. It’s true, though. At least it’s NOT radioactive.
Federalist 76 covers the appointment power of the Executive.
Derrick Reimer launched his new scheduling SaaS today. https://savvycal.com/
That was a smooth onboarding flow, Derrick. 👌
Here’s my summary of Federalist 75
I can’t get past how much overhead Gatsby adds to a project.
19:38 Cool, I have a working project with all the basics (inbound/outbound linking, block references, etc.) That was easier than I thought.
Good morning! It’s Wolf Shirt Wednesday
Here’s a summary of Federalist 74
Thank you, random internet strangers. <3
Reminds me of Scripting News
I’m already starting to see why generating a static site from Roam will be important: Roam loads the entire database locally, which isn’t ideal for sharing (also, page previews would be nice). #Digital Garden
14:19 Thinking about TypeScript and how it can help keep bad data out of a system when you have data coming in from many different sources (users, browsers, 3rd-party integrations).
If you define the edges of the system, you can receive
any typed data and sanitize it before allowing it to cross the boundary—from that point on you’re working with typed data.
For instance, given a
Client API, methods which are exposed to non-TS users receive input as type
These methods have tests to verify type conversion (to whatever type the data should be).
Beyond the public API, the rest of the (internal) system is strictly typed.
Number of calling arguments in public methods should also be tested, since outside of TS it’s easy to introduce
undefined values by omitting arguments.
Thanks to Julio for helping me think about TypeScript data structures
Love this “Enterprise” sales page: https://ghost.org/enterprise/
I speculated about whether companies were adding positions to oversee remote benefits on last week’s FounderQuest. It turns out they are: Hot new job title in a pandemic: ‘Head of remote work’
Welcome to my Digital Garden
For more on digital gardens, see Joel’s post.
A few notes on this project:
It must be easy to tend, otherwise it will wither
Therefore it must be a Roam database
I want to publish it to garden.joshuawood.net
The content is more important than the site
Hence, I’m shipping the public Roam database first
I’ll document the site as I build it. Thoughts on that tomorrow.