Maximum likelihood confidence intervals
The normal approximation to the Bernoulli sample relies on having a relatively large sample size and sample proportions far from the tails. The maximum likelihood estimate focuses on the log-transformed odds and this provides non-symmetric, efficient intervals for $p$ that should be used instead.
Define the log-odds as $\hat{\beta}_0 = \log(\hat{p}/(1-\hat{p}))$
A 1-$\alpha$ CI for $\beta_0$ is given by:
$$\text{CI}(\beta_0)_\alpha = \hat{\beta}_0 \pm \mathcal{Z}_{\alpha/2} \sqrt{1/(n\hat{p}(1-\hat{p})}$$
And this is back transformed into a (non-symmetric) interval for $p$ with:
$$\text{CI}(p)_\alpha = 1/(1+\exp(-\text{CI}(\beta_0)_\alpha)$$
This CI has the added benefit that proportions lie in the interval between 0 or 1, and the CI is always narrower than the normal interval while being of the correct level. You can get this very easily in R by specifying:
set.seed(123)
y <- rbinom(100, 1, 0.35)
plogis(confint(glm(y ~ 1, family=binomial)))
2.5 % 97.5 %
0.2795322 0.4670450
Exact binomial confidence intervals
In small samples, the normal approximation to the MLE--while better than the normal approximation to the sample proportion--may not be reliable. That is okay. $Y = n\hat{p}$ can be taken to follow a binomial$(n,p)$ density. Bounds for $\hat{p}$ can be found taking the 2.5th and 97.5-th percentiles from this distribution.
$$\text{CI}_\alpha = (F^{-1}_{\hat{p}}(0.025), F^{-1}_{\hat{p}}(0.975))$$
Rarely possible by-hand, an exact binomial confidence interval can be obtained for $p$ using computational methods.
qbinom(p = c(0.025, 0.975), size = length(y), prob = mean(y))/length(y)
[1] 0.28 0.47
Median unbiased confidence intervals
And if $p$ is 0 or 1 exactly, a median unbiased estimator can be used to obtain non-singular interval estimates based on the median unbiased probability function. You can trivially take the lower bound of the all-0 case as 0 WLOG. The upper bound is any proportion $p_{1-\alpha/2}$ that satisfies:
$$p_{1-\alpha/2} : P(Y = 0)/2 + P(Y > y) > 0.975$$
This is also a computational routine.
set.seed(12345)
y <- rbinom(100, 1, 0.01) ## all 0
cil <- 0
mupfun <- function(p) {
0.5*dbinom(0, 100, p) +
pbinom(1, 100, p, lower.tail = F) -
0.975
} ## for y=0 successes out of n=100 trials
ciu <- uniroot(mupfun, c(0, 1))$root
c(cil, ciu)
[1] 0.00000000 0.05357998 ## includes the 0.01 actual probability
The last two methods are implemented in the epitools
package in R.