Voltar para o Blog

Califórnia AB 1856: Por Que o Open Source Escapou da Lei de Verificação de Idade

Olá HaWkers, em 26 de agosto de 2026 o Senado da Califórnia aprovou a AB 1856 por 39 a 0, e no dia seguinte a Assembleia concordou com as emendas por 69 a 0. Zero votos contra nas duas casas. O texto tira quem distribui software sob licença livre da definição de "operating system provider" da Digital Age Assurance Act, a lei que entra em vigor em 1º de janeiro de 2027 e obriga sistemas operacionais a coletar a idade do usuário.

Você mantém um projeto open source e nunca pensou que uma lei estadual americana pudesse te alcançar? Pois ela quase alcançou. Neste artigo eu mostro o que a AB 1043 criou, qual é o texto exato que salvou o open source, quem continua dentro do escopo, e como auditar na prática se as licenças do seu projeto passam no critério.

O Que a AB 1043 Criou e Por Que Isso Assustou o Open Source

A Digital Age Assurance Act é a AB 1043, assinada pelo governador Gavin Newsom em 13 de outubro de 2025 e com vigência marcada para 1º de janeiro de 2027. A lógica dela é deslocar a verificação de idade do site para o sistema operacional.

Na prática, o texto obriga todo "operating system provider" a duas coisas. Primeiro, exibir na configuração inicial da conta uma tela pedindo data de nascimento, idade, ou ambos, do usuário principal do aparelho. Segundo, manter uma API de tempo real razoavelmente consistente que devolva a faixa etária daquele usuário para qualquer desenvolvedor que peça, no momento em que o aplicativo é baixado ou aberto.

As faixas são quatro: menos de 13 anos, de 13 a menos de 16, de 16 a menos de 18, e 18 ou mais. E o desenvolvedor do app não pode simplesmente ignorar o sinal: a lei manda tratar a resposta do sistema operacional ou da loja de aplicativos como indicador primário da faixa etária, salvo prova clara e convincente em contrário.

Agora leia isso pensando no Debian. Quem é o "provider"? O time de release? Cada mantenedor de pacote? A pessoa que espelha o repositório? Como um projeto sem CNPJ, sem tela de onboarding e sem contrato com o usuário final entrega uma API de idade em tempo real? Era um requisito impossível de cumprir e caro de descumprir, e foi exatamente esse o alarme que a comunidade levantou.

O Texto da Isenção: Duas Frases Que Mudam Tudo

A AB 1856 não revoga a AB 1043. Ela cirurgicamente reescreve duas definições.

A primeira trata do sistema operacional. "Operating system provider" passa a não alcançar quem distribui um sistema operacional ou aplicativo sob termos de licença que permitem ao destinatário copiar, redistribuir e modificar o software.

Repare que o critério não é uma lista de licenças aprovadas. É um teste funcional: a licença concede cópia, redistribuição e modificação? Então você está fora. GPL, MIT, BSD e Apache passam nesse teste sem esforço, o que tira Debian, Fedora, Ubuntu, Arch e a família BSD do escopo da lei.

A segunda definição é igualmente importante e passou mais despercebida. "Application" deixa de incluir componentes de software que não são oferecidos ao consumidor como aplicativo executável autônomo através de uma loja de aplicativos coberta.

Traduzindo: sua biblioteca no npm, seu pacote no PyPI, o que você publica via apt ou pacman e que não chega ao usuário final como um executável numa loja, também fica de fora das obrigações de nível de aplicação. Isso protege a camada inteira de dependências, que é onde a maioria de nós vive.

Quem Fica de Fora e Quem Continua Dentro

Vale ser preciso aqui, porque a manchete "Califórnia isenta o Linux" esconde metade da história.

Ficam de fora: distribuições Linux, os BSDs e qualquer sistema ou aplicativo distribuído sob licença que permita copiar, redistribuir e modificar. Ficam de fora também os componentes que não chegam ao consumidor como executável autônomo numa loja coberta.

Continuam dentro, e com prazo de 1º de janeiro de 2027 valendo: Windows, macOS, iOS e Android. Ou seja, os quatro sistemas por onde passa a esmagadora maioria dos usuários finais seguem obrigados a coletar idade e a expor o sinal. A lei não ficou menor, ela ficou mais precisa sobre quem consegue cumpri-la.

E falta um passo. Até o fechamento deste artigo, a AB 1856 ainda depende da assinatura do governador para virar lei. A aprovação unânime nas duas casas é um sinal forte, mas o processo não terminou.

Como Auditar as Licenças do Seu Projeto na Prática

O critério da lei é sobre os termos que você concede a quem recebe o software. Isso vira uma pergunta concreta e verificável: o campo de licença do seu projeto e das suas dependências declara algo que permite cópia, redistribuição e modificação?

Comece pelo seu próprio pacote. O campo license aceita um identificador SPDX, e é ele que ferramentas automatizadas leem:

{
  "name": "meu-projeto",
  "version": "1.4.0",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/usuario/meu-projeto.git"
  }
}

Um license ausente, ou o valor UNLICENSED, significa que você não concedeu nada. Sem concessão expressa de cópia, redistribuição e modificação, o teste da AB 1856 não é satisfeito, e o padrão do direito autoral é "todos os direitos reservados".

Agora a árvore de dependências. O script abaixo percorre o node_modules, lê a licença declarada de cada pacote e separa o que passa no critério do que precisa de olhar humano:

// audit-licencas.mjs - classifica as licenças da árvore de dependências
import { readdirSync, readFileSync, statSync } from 'node:fs'
import { join } from 'node:path'

// Licenças que concedem copiar, redistribuir e modificar
const PERMITE_REDISTRIBUIR = new Set([
  'MIT',
  'ISC',
  'BSD-2-Clause',
  'BSD-3-Clause',
  'Apache-2.0',
  'MPL-2.0',
  'GPL-2.0-only',
  'GPL-3.0-only',
  'LGPL-3.0-only',
  'AGPL-3.0-only',
])

function lerPacotes(raiz) {
  const encontrados = []

  for (const entrada of readdirSync(raiz)) {
    const caminho = join(raiz, entrada)
    if (!statSync(caminho).isDirectory()) continue

    // Escopos como @nuxt guardam os pacotes um nível abaixo
    if (entrada.startsWith('@')) {
      encontrados.push(...lerPacotes(caminho))
      continue
    }

    try {
      const pkg = JSON.parse(readFileSync(join(caminho, 'package.json'), 'utf8'))
      encontrados.push({ nome: pkg.name, licenca: pkg.license ?? null })
    } catch {
      // Diretório sem package.json legível: ignora
    }
  }

  return encontrados
}

const pacotes = lerPacotes('node_modules')
const revisar = pacotes.filter((p) => !p.licenca || !PERMITE_REDISTRIBUIR.has(p.licenca))

console.log(`Analisados: ${pacotes.length}`)
console.log(`Precisam de revisão manual: ${revisar.length}`)

for (const p of revisar) {
  console.log(`  ${p.nome} -> ${p.licenca ?? 'sem licença declarada'}`)
}

Duas ressalvas honestas sobre esse script. Ele lê a licença declarada, não o arquivo LICENSE real, e existem pacotes cujo package.json mente ou usa expressões SPDX compostas como (MIT OR Apache-2.0). E a lista acima é um ponto de partida técnico, não um parecer jurídico: MPL e AGPL permitem cópia, redistribuição e modificação, mas com contrapartidas que mudam bastante o que você assume ao redistribuir.

Um Portão de CI Que Reprova Licença Fora do Critério

Auditoria manual envelhece em uma semana. O lugar certo dessa verificação é no pipeline, falhando o build quando uma dependência nova entra sem licença compatível:

# .github/workflows/licencas.yml
name: Auditoria de licenças

on:
  pull_request:
    paths:
      - 'package.json'
      - 'yarn.lock'
      - 'package-lock.json'

jobs:
  auditar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      # Instala sem rodar scripts de pacote: só precisamos dos metadados
      - run: npm ci --ignore-scripts

      # O script sai com código diferente de zero quando encontra pendência
      - run: node audit-licencas.mjs

Para o script travar de fato o merge, basta encerrar com código de erro quando a lista de revisão não estiver vazia:

// Ao final de audit-licencas.mjs
if (revisar.length > 0) {
  console.error('\nDependências fora do critério de redistribuição livre.')
  console.error('Revise antes de seguir com o merge.')
  process.exit(1)
}

O ganho aqui vai muito além da AB 1856. Saber com precisão sob quais termos cada peça do seu projeto chega ao usuário é a base de qualquer conversa sobre conformidade, e agora também é a diferença entre estar dentro ou fora de uma obrigação regulatória concreta.

Do Outro Lado: Quem Vai Ter Que Consumir o Sinal de Idade

Se você publica um aplicativo numa loja coberta, a isenção não te alcança e você vai precisar pedir o sinal ao sistema operacional a partir de 2027.

O formato concreto dessa API ainda depende de cada fornecedor. O que a lei fixa são as quatro faixas e a obrigação de tratar o sinal como indicador primário. A assinatura abaixo é ilustrativa, para você isolar essa dependência agora e não espalhar a regulação pelo código inteiro:

// Faixas definidas pela AB 1043
type FaixaEtaria = 'menor_13' | 'de_13_a_15' | 'de_16_a_17' | 'adulto'

interface SinalIdade {
  faixa: FaixaEtaria
  origem: 'sistema_operacional' | 'loja' | 'indisponivel'
}

// Camada única de acesso: o resto do app nunca fala com a plataforma
export async function obterSinalIdade(): Promise<SinalIdade> {
  try {
    const bruto = await plataforma.requestAgeSignal()

    return { faixa: mapearFaixa(bruto), origem: 'sistema_operacional' }
  } catch {
    // Plataforma isenta ou sem suporte: não trave o app
    return { faixa: 'adulto', origem: 'indisponivel' }
  }
}

O catch não é detalhe. Depois da AB 1856 existe uma classe inteira de plataformas legitimamente isentas, que nunca vão responder a essa chamada. Um app que quebra quando o sinal não vem simplesmente deixa de funcionar em Linux, e isso é um bug seu, não da distribuição.

Vale a pena centralizar a decisão de produto em um único lugar, longe da chamada de plataforma:

// Uma função pura, fácil de testar, com a regra de negócio isolada
export function permiteRecursoAdulto(sinal: SinalIdade): boolean {
  // Sem sinal confiável, decida pela política do produto, não pelo acaso
  if (sinal.origem === 'indisponivel') return POLITICA_PADRAO_ADULTO

  return sinal.faixa === 'adulto'
}

O Que a EFF Continua Criticando

Seria cômodo fechar o assunto como uma vitória limpa, mas não é o que aconteceu.

A Electronic Frontier Foundation se opôs à AB 1856 por dois motivos distintos. O primeiro era o dano desproporcional que a AB 1043 impunha a desenvolvedores open source, e esse motivo a isenção resolveu. O segundo continua de pé: a fundação sustenta que qualquer regime de portão etário prejudica a liberdade de expressão, a privacidade e o anonimato de todos os usuários, isentos ou não.

Havia ainda um agravante. Versões anteriores do texto ampliavam o sistema de faixas etárias para navegadores e sites, o que multiplicaria o alcance da lei. Foi daí que veio o título do artigo da EFF em maio de 2026, "One Step Forward, Two Steps Back": um passo à frente para o open source, dois atrás para todo o resto. Em julho a legislatura recuou e removeu essa expansão, e foi a versão já podada que passou por unanimidade em agosto.

Ou seja, o texto que sobrou é bem melhor do que o que entrou. Mas a crítica de fundo ao modelo de verificação de idade no sistema operacional continua sem resposta.

O Que Isso Sinaliza Para a Regulação de Software

O detalhe mais interessante da AB 1856 é técnico, não político: o legislador escolheu definir a isenção pelos termos da licença e não por uma lista de projetos.

Uma lista envelheceria em um ano e viraria disputa sobre quem entra nela. Um teste funcional, "a licença permite copiar, redistribuir e modificar", se aplica sozinho a projetos que ainda nem existem. É o mesmo tipo de raciocínio que a comunidade vinha pedindo em outras frentes, como na votação do Debian sobre uso de IA generativa no código, onde a saída também foi definir um critério em vez de uma lista de ferramentas permitidas.

Duas consequências práticas para os próximos meses. A primeira é que o campo de licença do seu projeto deixou de ser burocracia de package.json e virou um fato com efeito legal. Vale conferir hoje se o que está declarado corresponde ao arquivo LICENSE do repositório.

A segunda é que esse desenho tende a ser copiado. Quando uma lei estadual americana passa por unanimidade nas duas casas, ela vira modelo de redação para outras jurisdições. Se o critério "permite copiar, redistribuir e modificar" se firmar como a fronteira padrão entre software regulado e não regulado, escolher uma licença deixa de ser só uma decisão de comunidade e passa a ser também uma decisão de exposição regulatória.

Bora pra cima! 🦅

📚 Quer Acompanhar o Que Vem Por Aí?

Este artigo cobriu a AB 1856 e a isenção do open source na lei de verificação de idade da Califórnia, mas o ecossistema muda toda semana e nem tudo vira artigo aqui.

No X eu compartilho o que estou testando, os bastidores dos projetos e as novidades que aparecem antes de virarem post.

Me Segue Lá

👉 Seguir @jeffbruchado no X

💡 Conteúdo diário sobre desenvolvimento, carreira e as ferramentas que eu realmente uso

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário